Axi-cel vs Liso-cel Analysis

aportugu Portuguese
February 07, 2024

Open libraries

Show code

Read in data

Read in tracking spreadsheet

Show code
db = read_excel(path = "Dataset 1.27.24.xlsx")

db <- db %>%
  filter(CAR.T.Product.Type == "Breyanzi" | CAR.T.Product.Type == "Yescarta") %>% # Include both Breyanzi and Yescarta
  filter(Acalabrutinib ==0) %>% # Remove patients treated on FH10418 RG1006269 acalabrutinib + yescarta
  filter(NKTR == 0) %>% # Remove patients treated on FH10802 RG1122036 NKTR-255 + breyanzi
  filter(Anakinra == 0) %>% # Remove patients treated on FH10373 RG1006866 Breyanzi + Anakinra
  filter(Disease != "BL" & Disease != "FL") %>% # Remove BL and FL
  filter(Infused == 1) %>% # Only include patients who received a CAR-T product
  mutate(
    Best.CR = ifelse(Best.response=="CR","1","0"),
    Best.PR = ifelse(Best.response=="PR","1","0"),
    Best.PD = ifelse(Best.response=="PD","1","0"),
    CRS.2.to.4 = ifelse(CRS.grade >=2,"1","0"),
    ICANS.2.to.4 = ifelse(ICANS.grade >=2, "1","0"),
    CRS.grade = factor(CRS.grade, levels = c("0","1","2","3","4")),
    ICANS.grade = factor(ICANS.grade, levels = c("0","1","2","3","4")),
    DOB = ymd(DOB),
    Leuka.date = ymd(Leuka.date),
    LD.date = ymd(LD.date),
    Infusion.Date = ymd(Infusion.Date),
    CRS.date = ymd(CRS.date),
    ICANS.date = ymd(ICANS.date),
    Initial.response.date = ymd(Initial.response.date),
    Date.of.relapse = ymd(Date.of.relapse),
    Date.of.death.or.last.contact = ymd(Date.of.death.or.last.contact),
    CRS.day = as.numeric(ifelse(CRS.grade !=0, CRS.date - Infusion.Date,"")),
    ICANS.day = as.numeric(ifelse(ICANS.grade !=0, ICANS.date - Infusion.Date,"")),
    CRS.ICANS.diff = as.numeric(ifelse(CRS.grade != 0 & ICANS.grade !=0, ICANS.date - CRS.date,"")),
    Days.to.DLC2 = Date.of.death.or.last.contact - Infusion.Date,
    Days.to.relapse2 = Date.of.relapse - Infusion.Date,
    Days.to.response = Initial.response.date - Infusion.Date,
    Vein.to.vein.time = Infusion.Date - Leuka.date,
    Bulky = ifelse(Largest.lesion >=5, "1","0")
    #Best.response = factor(Best.response, levels = c("CR","PR","SD","Mixed","PD","")),
    #Initial.response = factor(Initial.response, levels = c("CR","PR","SD","Mixed","PD",""))
  )

db$Best.CR <- as.factor(db$Best.CR)
db$Best.PR <- as.factor(db$Best.PR)
db$Best.PD <- as.factor(db$Best.PD)

Read in demographic data and join with master dataset

Show code
demographics = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/demographics/2023.12.13.demographics.xlsx")

dataset <- 
  left_join(
    x = db,
    y = select(demographics, "ArrivalDate", "uwid"),
    by = "uwid"
  )

dataset <- dataset %>%
  mutate(
    ArrivalDate = ymd(ArrivalDate),
    Arrival.to.vein.time = Infusion.Date - ArrivalDate
  )

Read in product order data and join with master dataset

Show code
Order = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/Order date/Order date.xlsx")

dataset <- 
  left_join(
    x = dataset,
    y = select(Order, "Order.date", "uwid"),
    by = "uwid"
  )

dataset <- dataset %>%
  mutate(
    Order.date = ymd(Order.date),
    Order.to.vein.time = Infusion.Date - Order.date
  )

Read in admissions data and join with master dataset

Show code
admissions = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/admissions/2023.12.13.Admissions.xlsx")

inpatient.duration.df <- admissions %>% # Data frame for all admissions between days 0 and 30
  filter(admitDay %in% (0:30) & PatientClass == "Inpatient") %>%
  group_by(uwid) %>%
  summarise(inpatient.duration = sum(days), admissions = n())

elective.admission.df <- admissions %>% # Data frame for elective admissions only
  filter(admitDay == 0 & PatientClass == "Inpatient") %>% # Inpatient admission on day 0
  group_by(uwid) %>%
  summarise(elective.duration = sum(days)) %>%
  mutate(elective.admission = 1)

dataset <- # Join all admission data
  left_join(
    x = dataset,
    y = inpatient.duration.df,
    by = "uwid",
  )

dataset <- # Join elective admission data
  left_join(
    x = dataset,
    y = elective.admission.df,
    by = "uwid"
  )

dataset <- dataset %>%
  replace_na(list(inpatient.duration = 0, admissions = 0, elective.duration = 0, elective.admission = 0)) # Get rid of NA values

Read in CBC data

Show code
CBC = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/labs/2023.12.13.hems.xlsx")

CBC$date = ymd(CBC$date)

CBC.df <- CBC %>% # Data frame for CBCs between days 0 and 30
  filter(anc != "" & day >=0 & day <=30) %>%
  group_by(uwid) %>%
  summarise(CBC.count = n(), WBC.min = min(wbc, na.rm=TRUE) / 1000, Plt.min = min(TotPlateletCnt, na.rm=TRUE) / 1000, Hgb.min = min(HgbAmt, na.rm=TRUE), ANC.min = min(anc, na.rm=TRUE) / 1000, ALC.min = min(lym, na.rm=TRUE) / 1000 )

CBC.30.df <- CBC %>% # Data frame for CBCs between days 0 and 30
  filter(anc != "" & day >=25 & day <=30) %>%
  group_by(uwid) %>%
  slice_max(day, with_ties = FALSE) %>%
  summarise(CBC.count = n(), WBC.30 = max(wbc, na.rm=TRUE) / 1000, Plt.30 = max(TotPlateletCnt, na.rm=TRUE) / 1000, Hgb.30 = max(HgbAmt, na.rm=TRUE), ANC.30 = max(anc, na.rm=TRUE) / 1000, ALC.30 = min(lym, na.rm=TRUE) / 1000 )
  
WBC.nadir.df <- CBC %>%
  filter(wbc != "" & day >=0 & day <=30) %>%
  group_by(uwid) %>%
  slice_min(wbc, with_ties = FALSE) %>%
  transmute(WBC_day_nadir = day)%>%
  select(WBC_day_nadir, uwid)

dataset <- # Join CBC data
  left_join(
    x = dataset,
    y = CBC.df,
    by = "uwid"
  )

dataset <- # Join ANC day nadir
  left_join(
    x = dataset,
    y = WBC.nadir.df,
    by = "uwid"
  )

dataset <- # Join ANC day nadir
  left_join(
    x = dataset,
    y = CBC.30.df,
    by = "uwid"
  )

neutropenic.df <- CBC %>%
  filter(anc != "" & anc <500 & day >=0 & day <=30) %>%
  group_by(uwid) %>%
  summarise(
    neutropenic.days = n()
  )

dataset <- # Join neutropenic days info
  left_join(
    x = dataset,
    y = neutropenic.df,
    by = "uwid"
  ) %>%
  mutate(
    neutropenic.days = ifelse(is.na(neutropenic.days),0,neutropenic.days)
  )


CBC.d0.df <- CBC %>% ## Data frame for day 0
  filter(day == 0) %>%
  group_by(uwid) %>%
  summarise(ANC.d0 = mean(anc, na.rm=TRUE) / 1000, ALC.d0 = mean (lym, na.rm=TRUE) / 1000)

dataset <-
  left_join(
    x = dataset,
    y = CBC.d0.df,
    by = "uwid"
  ) %>%
  mutate(
    ANC.d0 = ifelse(ANC.d0 == "NaN", NA, ANC.d0),
    ALC.d0 = ifelse(ALC.d0 == "NaN", NA, ANC.d0)
  )

Read in other lab data

Show code
labs = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/labs/2023.12.13.labs.xlsx")

labs$date = ymd(labs$date)

labs.df <- labs %>% # Data frame for labs between days 0 and 30
  filter(day >=0 & day <=30) %>%
  group_by(uwid) %>%
  summarise(labs.count = n() , ALT.max = max(ALT_u_l, na.rm=TRUE), AST.max = max(AST_u_l, na.rm=TRUE), cre.min = min(CRE_mg_dl, na.rm=TRUE), cre.max = max(CRE_mg_dl, na.rm=TRUE), CRP.max = max(CRP_mg_l, na.rm=TRUE), ddimer.max = max(d_dimer, na.rm=TRUE), ferritin.max = max(ferritin_ng_ml, na.rm=TRUE), fibrinogen.min = min(fibrinogen_mg_dl, na.rm=TRUE), IL6.max = max(IL6_pg_ml, na.rm=TRUE), LDH.max = max(LD_u_l, na.rm=TRUE), LDH.min = min(LD_u_l, na.rm=TRUE), trop.max = max(troponin_ng_ml, na.rm=TRUE) ) 

labs.d3.df <- labs %>% ## Data frame for day 3
  filter(day == 3) %>%
  group_by(uwid) %>%
  summarise(ferritin.d3 = mean(ferritin_ng_ml, na.rm=TRUE), LDH.d3 = mean(LD_u_l, na.rm=TRUE), IL6.d3 = max(IL6_pg_ml, na.rm=TRUE),  CRP.d3 = max(CRP_mg_l, na.rm=TRUE))

labs.d0.df <- labs %>% ## Data frame for day 0
  filter(day == 0) %>%
  group_by(uwid) %>%
  summarise(ferritin.d0 = mean(ferritin_ng_ml, na.rm=TRUE), LDH.d0 = mean(LD_u_l, na.rm=TRUE), IL6.d0 = max(IL6_pg_ml, na.rm=TRUE) )

labs.df[sapply(labs.df, is.infinite)] <- NA ## Change any -inf values to NA
labs.d3.df[sapply(labs.d3.df, is.infinite)] <- NA ## Change any -inf values to NA
labs.d0.df[sapply(labs.d0.df, is.infinite)] <- NA ## Change any -inf values to NA

dataset <-
  left_join(
    x = dataset,
    y = labs.df,
    by = "uwid"
  )

dataset <- # Join ANC day nadir
  left_join(
    x = dataset,
    y = labs.d3.df,
    by = "uwid"
  )

dataset <- # Join ANC day nadir
  left_join(
    x = dataset,
    y = labs.d0.df,
    by = "uwid"
  )

Read in blood culture data

Show code
blood.culture = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/id/2023.12.13.ID_ALL.xlsx")

blood.culture$date = ymd(blood.culture$date)

Pos.BCx <- blood.culture %>%
  select(uwid, bact, organism, date, day) %>%
  group_by(uwid) %>%
  filter(bact == "1" & day >=0) %>%
  distinct() %>%
  slice_min(day) %>%
  transmute(
    uwid,
    Pos.BCx = 1,
    BCx.day = day,
    BCx.date = date,
    BCx.organism = organism,
  )

Pos.CMV <- blood.culture %>%
  select(uwid, viral, organism, date, day, value) %>%
  group_by(uwid) %>%
  filter(organism == "CMV" & day >=0) %>%
  distinct() %>%
  summarise(CMV.first.day = min(day, na.rm = TRUE), CMV.last.day = max(day, na.rm = TRUE), CMV.peak.level = max(value, na.rm = TRUE)) %>%
  mutate(
    CMV = 1
  )

Pos.CMV[sapply(Pos.CMV, is.infinite)] <- NA ## Change any -inf values to NA

dataset <- # Join BCx data
  left_join(
    x = dataset,
    y = Pos.BCx,
    by = "uwid"
  )

dataset <- # Join CMV data
  left_join(
    x = dataset,
    y = Pos.CMV,
    by = "uwid"
  )

dataset <- dataset %>%
  mutate(
    Pos.BCx = ifelse( is.na(Pos.BCx) ,0,Pos.BCx),
    CMV = ifelse( is.na(CMV), 0, CMV ),
    CMV.peak.level = ifelse( is.na(CMV.peak.level), 0, CMV.peak.level)
  )

Determine the baseline pre-LD lab values

Show code
avg = 1

days = 14

CBC.with.LD.date <- # join the LD dates to the CBC dataframe
  left_join(
    x = CBC,
    y = dataset %>% select(uwid, LD.date),
    by = "uwid"
  )

## CBC
preLD.CBC.df <- CBC.with.LD.date %>%
  filter(LD.date >= date & LD.date - date <days & !is.na(wbc) ) %>%
  group_by(uwid) %>%
  slice_min(LD.date - date, n=avg) %>%
  summarise(WBC.preLD = mean(wbc, na.rm=TRUE) / 1000, Plt.preLD = mean(TotPlateletCnt, na.rm=TRUE) / 1000, Hgb.preLD = mean(HgbAmt, na.rm=TRUE))

dataset <- # join pre-LD CBC lab values
  left_join(
    x = dataset,
    y = preLD.CBC.df,
    by = "uwid"
  )

## Differential (ALC and ANC)
preLD.ALC.ANC.df <- CBC.with.LD.date %>%
  filter(LD.date >= date & LD.date - date <days & !is.na(anc) ) %>%
  group_by(uwid) %>%
  slice_min(LD.date - date, n=avg) %>%
  summarise(ANC.preLD = mean(anc, na.rm=TRUE) / 1000, ALC.preLD = mean (lym, na.rm=TRUE) / 1000)

dataset <- # join pre-LD CBC lab values
  left_join(
    x = dataset,
    y = preLD.ALC.ANC.df,
    by = "uwid"
  )



labs.with.LD.date <- # join the LD dates to the labs dataframe
  left_join(
    x = labs,
    y = dataset %>% select(uwid, LD.date),
    by = "uwid"
  )


## LDH
preLD.LDH.df <- labs.with.LD.date %>%
  filter(LD.date >= date & LD.date - date <days & !is.na(LD_u_l) ) %>% 
  group_by(uwid) %>%
  slice_min(LD.date - date, n=avg, na_rm = TRUE) %>%
  summarise(LDH.preLD = mean(LD_u_l, na.rm=TRUE))

dataset <- # join pre-LD lab values
  left_join(
    x = dataset,
    y = preLD.LDH.df,
    by = "uwid"
  )

dataset <- dataset %>%
  mutate(
    High.LDH = ifelse(LDH.preLD >=210,1,0),
    LDH.status = factor( case_when(
      LDH.preLD <210 ~ 0,
      LDH.preLD >=210 & LDH.preLD <=420 ~ 1,
      LDH.preLD >420 ~ 2), 
      levels = c(0,1,2) )
  )



## Renal function
preLD.Cr.df <- labs.with.LD.date %>%
  filter(LD.date >= date & LD.date - date <days & !is.na(CRE_mg_dl) ) %>%
  group_by(uwid) %>%
  slice_min(LD.date - date, n=avg, na_rm = TRUE) %>%
  summarise(cre.preLD = mean(CRE_mg_dl, na.rm=TRUE))

dataset <- # join pre-LD lab values
  left_join(
    x = dataset,
    y = preLD.Cr.df,
    by = "uwid"
  )


## Ferritin
preLD.ferritin.df <- labs.with.LD.date %>%
  filter(LD.date >= date & LD.date - date <days & !is.na(ferritin_ng_ml) ) %>%
  group_by(uwid) %>%
  slice_min(LD.date - date, n=avg, na_rm = TRUE) %>%
  summarise(ferritin.preLD = mean(ferritin_ng_ml, na.rm=TRUE))

dataset <- # join pre-LD lab values
  left_join(
    x = dataset,
    y = preLD.ferritin.df,
    by = "uwid"
  )


## CRP
preLD.CRP.df <- labs.with.LD.date %>%
  filter(LD.date >= date & LD.date - date <days & !is.na(CRP_mg_l) ) %>% 
  group_by(uwid) %>%
  slice_min(LD.date - date, n=avg, na_rm = TRUE) %>%
  summarise(CRP.preLD = mean(CRP_mg_l, na.rm=TRUE))

dataset <- # join pre-LD lab values
  left_join(
    x = dataset,
    y = preLD.CRP.df,
    by = "uwid"
  )

Read in BP data and determine pre-LD baseline

Show code
BP = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/vs/2023.12.13.BP.xlsx")

BP$date = ymd(BP$date)

BP.post.df <- BP %>% # Data frame for labs between days 0 and 30
  filter(day >=0 & day <=30) %>%
  group_by(uwid) %>%
  summarise( BP.count = n() , SBP.max = max(SBP, na.rm=TRUE), DBP.max = max(DBP, na.rm=TRUE), SBP.min = min(SBP, na.rm=TRUE), DBP.min = min(DBP, na.rm=TRUE) ) 

dataset <- # post-infusion values
  left_join(
    x = dataset,
    y = BP.post.df,
    by = "uwid"
  )


BP.with.LD.date <- # join the LD dates to the BP dataframe
  left_join(
    x = BP,
    y = dataset %>% select(uwid, LD.date),
    by = "uwid"
  )

preLD.BP.df <- BP.with.LD.date %>%
  filter(LD.date >= date & LD.date - date <10) %>% ## Within 14 days prior to LD
  group_by(uwid) %>%
  slice_min(LD.date - date, n=3) %>%
  summarise(SBP.preLD = mean(SBP, na.rm=TRUE), DBP.preLD = mean(DBP, na.rm=TRUE) )

dataset <- # join pre-LD BP lab values
  left_join(
    x = dataset,
    y = preLD.BP.df,
    by = "uwid"
  ) %>%
  mutate(
    MAP.preLD = DBP.preLD + (SBP.preLD - DBP.preLD)/3,
    MAP.min = DBP.min + (SBP.min - DBP.min)/3
  )

Read in tocilizumab data

Show code
toci = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/meds/2023.12.13.tocilizumab.xlsx")
toci$date = ymd(toci$date)

toci.df <- toci %>%
  select(uwid, date, day, Dose) %>%
  group_by(uwid) %>%
  filter(day >=0) %>%
  summarise(toci.first.day = min(day, na.rm=TRUE), toci.first.date = min(date, na.rm=TRUE), toci.last.day = max(day, na.rm=TRUE), toci.last.date = max(date, na.rm=TRUE), toci.doses = n())

dataset <- # join pre-LD CBC lab values
  left_join(
    x = dataset,
    y = toci.df,
    by = "uwid"
  ) %>%
  mutate(
    toci.doses = ifelse(is.na(toci.doses),0,toci.doses) # Set NA values to 0
  )

Read in dexamethasone data

Show code
dex = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/meds/2023.12.13.dexamethasone.xlsx")
dex$date = ymd(dex$date)

dex.df <- dex %>%
  select(uwid, date, day, Dose, AdministrationRoute) %>%
  group_by(uwid) %>%
  filter(day >=0 & AdministrationRoute != "Oral" & AdministrationRoute != "PO" & AdministrationRoute != "EYE-Left" & AdministrationRoute != "EYE-Right") %>%
  summarise(dex.first.day = min(day, na.rm=TRUE), dex.first.date = min(date, na.rm=TRUE), dex.last.day = max(day, na.rm=TRUE), dex.last.date = max(date, na.rm=TRUE), dex.doses = n())

dataset <- # join pre-LD CBC lab values
  left_join(
    x = dataset,
    y = dex.df,
    by = "uwid"
  ) %>%
  mutate(
    dex.doses = ifelse(is.na(dex.doses),0,dex.doses) # Set NA values to 0
  )

Read in cefepime data

Show code
cefepime = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/meds/2023.12.13.cefepime.xlsx")
cefepime$date = ymd(cefepime$date)

cefepime.df <- cefepime %>%
  select(uwid, date, day, Dose) %>%
  group_by(uwid) %>%
  filter(day >=0) %>%
  summarise(cefepime.first.day = min(day, na.rm=TRUE), cefepime.first.date = min(date, na.rm=TRUE), cefepime.last.day = max(day, na.rm=TRUE), cefepime.last.date = max(date, na.rm=TRUE), cefepime.doses = n())

dataset <- # join pre-LD CBC lab values
  left_join(
    x = dataset,
    y = cefepime.df,
    by = "uwid"
  ) %>%
  mutate(
    cefepime.doses = ifelse(is.na(cefepime.doses),0,cefepime.doses) # Set NA values to 0
  )

Read in vancomycin data

Show code
vancomycin = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/meds/2023.12.13.vancomycin.xlsx")
vancomycin$date = ymd(vancomycin$date)

vancomycin.df <- vancomycin %>%
  select(uwid, date, day, Dose) %>%
  group_by(uwid) %>%
  filter(day >=0) %>%
  summarise(vancomycin.first.day = min(day, na.rm=TRUE), vancomycin.first.date = min(date, na.rm=TRUE), vancomycin.last.day = max(day, na.rm=TRUE), vancomycin.last.date = max(date, na.rm=TRUE), vancomycin.doses = n())

dataset <- # join pre-LD CBC lab values
  left_join(
    x = dataset,
    y = vancomycin.df,
    by = "uwid"
  ) %>%
  mutate(
    vancomycin.doses = ifelse(is.na(vancomycin.doses),0,vancomycin.doses) # Set NA values to 0
  )

Read in norepinephrine data

Show code
norepinephrine = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/meds/2023.12.13.norepinephrine.xlsx")
norepinephrine$date = ymd(norepinephrine$date)

norepinephrine.df <- norepinephrine %>%
  select(uwid, date, day, Dose) %>%
  group_by(uwid) %>%
  filter(day >=0) %>%
  summarise(norepinephrine.first.day = min(day, na.rm=TRUE), norepinephrine.first.date = min(date, na.rm=TRUE), norepinephrine.last.day = max(day, na.rm=TRUE), norepinephrine.last.date = max(date, na.rm=TRUE), norepinephrine.doses = n())

dataset <- # join pre-LD CBC lab values
  left_join(
    x = dataset,
    y = norepinephrine.df,
    by = "uwid"
  ) %>%
  mutate(
    norepinephrine.doses = ifelse(is.na(norepinephrine.doses),0,norepinephrine.doses) # Set NA values to 0
  )

Read in temp data

Show code
temperature = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/vs/2023.12.13.temperature.xlsx")
temperature$date = ymd(temperature$date)

fever.df <- temperature %>%
  select(uwid, date, day, temp_C) %>%
  group_by(uwid) %>%
  filter(day >=0 & temp_C >=38) %>%
  summarise(fever.first.day = min(day, na.rm=TRUE), fever.first.date = min(date, na.rm=TRUE), fever.last.day = max(day, na.rm=TRUE), fever.last.date = max(date, na.rm=TRUE), fever.days = n_distinct(day))

dataset <- # join pre-LD CBC lab values
  left_join(
    x = dataset,
    y = fever.df,
    by = "uwid"
  )

Read in ICE score data

Show code
ICE = read_excel(path = "/Users/aportugu/Desktop/CD19 project/EMR data/vs/2023.12.13.ICEscores.xlsx")
ICE$date = ymd(ICE$date)

ICE.df <- ICE %>%
  select(uwid, date, day, ICE.SCORE, ICE.ATTENTION, ICE.FOLLOW.COMMANDS, ICE.NAME.OBJECTS, ICE.ORIENTATION, ICE.WRITING) %>%
  group_by(uwid) %>%
  filter(day >=0) %>%
  summarise(ICE.min = min(ICE.SCORE, na.rm=TRUE), ICE.attention.min = min(ICE.ATTENTION, na.rm=TRUE), ICE.follow.commands.min = min(ICE.FOLLOW.COMMANDS, na.rm=TRUE), ICE.name.objects.min = min(ICE.NAME.OBJECTS, na.rm=TRUE), ICE.orientation.min = min(ICE.ORIENTATION, na.rm=TRUE), ICE.writing.min = min(ICE.WRITING, na.rm=TRUE))

dataset <- # join pre-LD CBC lab values
  left_join(
    x = dataset,
    y = ICE.df,
    by = "uwid"
  )

ICE.less.than.10.df <- ICE %>%
  select(uwid, date, day, ICE.SCORE, ICE.ATTENTION, ICE.FOLLOW.COMMANDS, ICE.NAME.OBJECTS, ICE.ORIENTATION, ICE.WRITING) %>%
  group_by(uwid) %>%
  filter(day >=0 & ICE.SCORE <10) %>%
  summarise(ICE.less.than.10 = n_distinct(day))

dataset <- # join pre-LD CBC lab values
  left_join(
    x = dataset,
    y = ICE.less.than.10.df,
    by = "uwid"
  )

All BP data points

Show code
BPdata = filter(BP, day >=-15 ) %>%
  select(day, SBP, DBP, time, uwid) %>%
  mutate(
    time.percent = sapply( strsplit(time,":"),
                           function(x) {
                             x <- as.numeric(x)
                             x[1]/24
                           }
    ),
    day = ifelse(day>=0, day + time.percent, day - time.percent),
    MAP = SBP/3 + DBP * 2/3
  )

BPdata <- # join pre-LD CBC lab values
  left_join(
    x = BPdata,
    y = dataset %>%
      select(CAR.T.Product.Type, uwid, Study.No, CRS.grade, ICANS.grade),
    by = "uwid"
  )

All ANC data points

Show code
CBCdata = filter(CBC, day >=-15 ) %>%
  select(day, ancx, lymx, HgbAmt, TotPlateletCnt, time, uwid) %>%
  mutate(
    time.percent = sapply( strsplit(time,":"),
                           function(x) {
                             x <- as.numeric(x)
                             x[1]/24
                           }
    ),
    day = ifelse(day>=0, day + time.percent, day - time.percent),
  )

CBCdata <-
  left_join(
    x = CBCdata,
    y = dataset %>%
      select(CAR.T.Product.Type, uwid, Study.No),
    by = "uwid"
  )

Propensity scores

Regression analysis for treatment allocation

Show code
variables <- c("CAR.T.Product.Type", "Age", "Second.line", "LDH.preLD", "ALC.preLD", "ASCT", "Largest.lesion", "tDLBCL", "ECOG.status", "Extranodal", "Bridging.response.category")

data1 <- dataset %>% 
  drop_na(LDH.preLD, ALC.preLD, Bridging.response.category, ECOG) %>%
  mutate(
    Bulky = ifelse(Largest.lesion >=5,1,0),
    ECOG.status = ifelse(ECOG >=2,1,0),
    ALC.low = ifelse(ALC.preLD <=1,1,0),
    CAR.T.Product.Type = recode(CAR.T.Product.Type, "Breyanzi" = 1, "Yescarta" = 0),
    Bridging.response.category = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD", "3"="Unknown response"), levels = c("No bridging","CR/PR","SD/PD", "Unknown response")),
  )

uv_tab <- tbl_uvregression(
    data1[c(variables)],
    method = glm,
    y = CAR.T.Product.Type,
    method.args = list(family = binomial),
    exponentiate = TRUE
  ) %>%
  sort_p()


mv_tab<-glm(CAR.T.Product.Type ~ Age + Second.line + LDH.preLD + ALC.preLD + ASCT + Largest.lesion + tDLBCL + ECOG.status + Extranodal + Bridging.response.category, data=data1, family=binomial) %>%
  tbl_regression(exponentiate=TRUE)

tbl_merge(list(uv_tab, mv_tab), tab_spanner = c("**Univariate**", "**Multivariable**"))
Characteristic Univariate Multivariable
N OR1 95% CI1 p-value OR1 95% CI1 p-value
Age 148 1.06 1.03, 1.10 <0.001 1.06 1.03, 1.11 0.001
Bridging.response.category 148





    No bridging


    CR/PR
3.30 1.23, 8.98 0.017 2.64 0.83, 8.46 0.10
    SD/PD
1.77 0.76, 4.09 0.2 2.84 0.96, 8.80 0.062
    Unknown response
46,954,082 0.00, NA >0.9 38,025,973 0.00, NA >0.9
Second.line 148 2.48 0.84, 7.50 0.10 1.95 0.51, 7.74 0.3
ASCT 148 0.46 0.15, 1.24 0.15 0.50 0.14, 1.49 0.2
ALC.preLD 148 1.41 1.00, 2.41 0.2 1.24 0.96, 2.24 0.3
tDLBCL 148 1.56 0.68, 3.51 0.3 1.70 0.61, 4.66 0.3
LDH.preLD 148 1.00 1.00, 1.00 0.3 1.00 1.00, 1.00 0.3
Largest.lesion 148 0.95 0.85, 1.05 0.3 0.93 0.81, 1.06 0.3
ECOG.status 148 0.74 0.29, 1.78 0.5 0.74 0.23, 2.16 0.6
Extranodal 148 0.88 0.44, 1.76 0.7 1.11 0.47, 2.68 0.8
1 OR = Odds Ratio, CI = Confidence Interval

IPTW

Show code
IPTW.data <- dataset %>% 
  #drop_na(LDH.preLD, ALC.preLD, Bridging.response.category, ECOG) %>%
  mutate(
    Age.65 = ifelse(Age >=65,1,0),
    Male.sex = ifelse(Sex == "M",1,0),
    Bulky = ifelse(Largest.lesion >=5,1,0),
    ECOG.status = ifelse(ECOG >=2,1,0)
  )

## Use the WeightIt function to generate propensity scores and weights
W.out <- weightit(CAR.T.Product.Type ~ Age + Second.line + ASCT + Largest.lesion + tDLBCL + ECOG.status + Extranodal, 
                  data=IPTW.data, 
                  method = "glm", 
                  estimand = "ATE",
                  stabilize = TRUE)
summary = summary(W.out)

bal.tab(W.out, stats = c("m", "v"), thresholds = c(m=0.25), binary = "std")
Balance Measures
                   Type Diff.Adj     M.Threshold V.Ratio.Adj
prop.score     Distance   0.0848 Balanced, <0.25      1.2909
Age             Contin.  -0.1721 Balanced, <0.25      1.5656
Second.line      Binary   0.0487 Balanced, <0.25           .
ASCT             Binary   0.0734 Balanced, <0.25           .
Largest.lesion  Contin.  -0.0718 Balanced, <0.25      0.3979
tDLBCL           Binary  -0.0855 Balanced, <0.25           .
ECOG.status      Binary  -0.0856 Balanced, <0.25           .
Extranodal       Binary  -0.0411 Balanced, <0.25           .

Balance tally for mean differences
                    count
Balanced, <0.25         8
Not Balanced, >0.25     0

Variable with the greatest mean difference
 Variable Diff.Adj     M.Threshold
      Age  -0.1721 Balanced, <0.25

Effective sample sizes
           Breyanzi Yescarta
Unadjusted    50.      99.  
Adjusted      40.48    86.18
Show code
love.plot(W.out,
          binary = "std",
          line = TRUE, 
          abs = TRUE,
          thresholds = c(m=0.25),
          var.order = "unadjusted",
            var.names = c(
              Age = "Age",
              prop.score = "Distance",
              Male.sex = "Male sex",
              Second.line = "Second line",
              LDH.preLD = "LDH pre-LD",
              ALC.preLD = "ALC pre-LD",
              Bridging = "Bridging",
              ASCT = "Prior ASCT",
              Largest.lesion = "Largest lesion",
              Bridging.response.category = "Bridging response",
              tDLBCL = "tDLBCL vs other",
              ECOG.status = "ECOG\u22652"
          ))
Show code
IPTW.data$weights <- W.out$weights * (summary$effective.sample.size$Breyanzi[2] + summary$effective.sample.size$Yescarta[2])/sum(W.out$weights) # Attach normalized weights to a dataset

IPTW.data$ps <- W.out$ps

PSM

Show code
PSM.data <- dataset %>% 
  #drop_na(LDH.preLD, ALC.preLD, Bridging.response.category, ECOG) %>%
  mutate(
    Age.65 = ifelse(Age >=65,1,0),
    Male.sex = ifelse(Sex == "M",1,0),
    Bulky = ifelse(Largest.lesion >=5,1,0),
    ECOG.status = ifelse(ECOG >=2,1,0),
    Bridging.response.category = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD", "3"="Unknown response"), levels = c("No bridging","CR/PR","SD/PD", "Unknown response")),
    ALC.low = ifelse(ALC.preLD <=1,1,0),
    CAR.T.Product.Type = ifelse(CAR.T.Product.Type == "Breyanzi",1,0)
  )


m.out <- matchit(CAR.T.Product.Type ~ Age + Second.line + ASCT + Largest.lesion + tDLBCL + ECOG.status + Extranodal, data=PSM.data, method = "full", distance = "glm", link = "logit") # Full matching


bal.tab(m.out, stats = c("m", "v"), thresholds = c(m=0.25), binary = "std")
Balance Measures
                   Type Diff.Adj     M.Threshold V.Ratio.Adj
distance       Distance  -0.0027 Balanced, <0.25      0.9453
Age             Contin.  -0.0776 Balanced, <0.25      1.1420
Second.line      Binary   0.1300 Balanced, <0.25           .
ASCT             Binary  -0.0300 Balanced, <0.25           .
Largest.lesion  Contin.  -0.0545 Balanced, <0.25      2.5635
tDLBCL           Binary   0.0027 Balanced, <0.25           .
ECOG.status      Binary  -0.0591 Balanced, <0.25           .
Extranodal       Binary  -0.2025 Balanced, <0.25           .

Balance tally for mean differences
                    count
Balanced, <0.25         8
Not Balanced, >0.25     0

Variable with the greatest mean difference
   Variable Diff.Adj     M.Threshold
 Extranodal  -0.2025 Balanced, <0.25

Sample sizes
                     Control Treated
All                    99.        50
Matched (ESS)          26.27      50
Matched (Unweighted)   99.        50
Show code
m.out_NN <- matchit(CAR.T.Product.Type ~ Age + Second.line + ASCT + Largest.lesion + tDLBCL + ECOG.status + Extranodal, data=PSM.data, method = "nearest", distance = "glm", link = "logit") # Nearest neighbor matching for comparison


love.plot(m.out, stats = c("m"), abs = TRUE,
          binary = "std",
          drop.distance = FALSE, 
          weights = list(nn = m.out_NN),
          var.order = "unadjusted",
          line = TRUE, 
          thresholds = c(m=0.25, ks = 0.05),
          sample.names = c("Original", "Full Matching", "Nearest Neighbor Matching"),
          position = "bottom",
          var.names = c(
            prop.score = "Distance",
            Bridging = "Bridging",
            LDH.preLD = "LDH pre-LD",
            LDH.status = "LDH status",
            ALC.preLD = "ALC pre-LD",
            Age.62 = "Age \u226562",
            Male.sex = "Male sex",
            Second.line = "Second line",
            ASCT = "Prior ASCT",
            Largest.lesion = "Largest lesion",
            HCT.CI = "HCT-CI",
            ECOG.status = "ECOG \u22652",
            Bridging.response.category = "Bridging response",
            tDLBCL = "tDLBCL vs other"

          )
          )
Show code
# Create a dataset with PSM weights using full matching
m.data <- match.data(m.out) %>%
  mutate(
    CAR.T.Product.Type = ifelse(CAR.T.Product.Type == 1, "Breyanzi","Yescarta")
  )

m.data_NN <- match.data(m.out_NN)

Scatterplot of weights

Show code
ggplot(IPTW.data %>% mutate(Product = CAR.T.Product.Type, Product = recode(Product, "Breyanzi"="Liso-cel","Yescarta"="Axi-cel")), aes(x=ps, y = weights, color = Product)) + 
  geom_point(shape = 16) +
  theme_classic() + 
  labs(x = "Propensity score", y = "Weights") # Add a legend label
Show code
ggplot(m.data, aes(x=distance, y = weights, color = CAR.T.Product.Type)) + 
  geom_point(shape = 16) +
  theme_minimal() + 
  ggtitle("PSM") +
  labs(x = "Propensity score", y = "Weights") # Add a legend label

TABLES

Baseline characteristics

Show code
theme_gtsummary_compact()

dataset %>%
  transmute(
    #"Age \u226565 years" = ifelse(Age >=65,1,0),
    "Age (years)" = Age,
    "Male sex" = ifelse(Sex == "M", "Yes","No"),
    "ECOG PS" = factor( recode(ECOG, "0"="0-1","1"="0-1","2"="\u22652","3"="\u22652","4"="\u22652"), levels = c("0-1", "\u22652") ),
    "HCT-CI" = HCT.CI,
    "TRANSCEND eligible" = TRANSCEND,
    "Second line" = Second.line,
    "Prior ASCT" = ASCT,
    #"Received bridging" = Bridging,
    "Bridging response category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD", "3" = "Unknown response"), levels = c("No bridging","CR/PR","SD/PD", "Unknown response")),
    "Disease subtype" = Disease,
    "LDH" = LDH.preLD,
    "ALC" = ALC.preLD,
    #"Elevated LDH (\u2265210 U/L)" = ifelse(LDH.preLD >=210,"Yes","No"),
    #"LDH status" = factor(recode(LDH.status, "0" = "\u2264ULN", "1" = "[ULN; 2x ULN]", "2"=">2x ULN"), levels = c("\u2264ULN", "[ULN; 2x ULN]", ">2x ULN") ),
    "Largest lesion (cm)" = Largest.lesion,
    #"Bulky (\u22655 cm)" = ifelse(Bulky == 1, "Yes","No"),
    "Extranodal" = ifelse(Extranodal == 1, "Yes","No"),
    "Out-of-spec" = ifelse(EAP == 1,"Yes","No"),
    "Product" = factor(recode(CAR.T.Product.Type, "Breyanzi"= "Liso-cel", "Yescarta" = "Axi-cel"), levels = c("Liso-cel","Axi-cel"))
  ) %>%
  tbl_summary(
    missing = "ifany",
    #sort = all_categorical() ~ "frequency",
    type = c("HCT-CI" = "continuous", "ECOG" = "continuous"),
    #type = c("HCT-CI" = "continuous", "ECOG" = "continuous", "Max CRS grade" = "continuous", "Max ICANS grade" = "continuous", "Total inpatient duration (days)" = "continuous", "Days with fever" ~ "continuous"),
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)",
      "Age (years)" ~"{median} ({min} to {max})"
      #"Total inpatient duration (days)" ~ "{median} ({min} to {max})"
      #"HCT-CI" ~ "{median} ({min} to {max})"
    )
  ) %>%
  bold_labels
Characteristic N = 1491
Age (years) 62 (26 to 83)
Male sex 93 (62%)
ECOG PS
    0-1 120 (81%)
    ≥2 29 (19%)
HCT-CI 1.00 (1.00, 3.00)
TRANSCEND eligible 102 (68%)
Second line 15 (10%)
Prior ASCT 24 (16%)
Bridging response category
    No bridging 88 (59%)
    CR/PR 21 (14%)
    SD/PD 36 (24%)
    Unknown response 4 (2.7%)
Disease subtype
    DLBCL 104 (70%)
    HGBCL 7 (4.7%)
    PMBCL 5 (3.4%)
    TCHRLBCL 2 (1.3%)
    tDLBCL 31 (21%)
LDH 186 (151, 292)
    Unknown 1
ALC 0.60 (0.33, 0.99)
Largest lesion (cm) 3.2 (1.6, 5.5)
Extranodal 87 (58%)
Out-of-spec 13 (8.7%)
Product
    Liso-cel 50 (34%)
    Axi-cel 99 (66%)
1 Median (Range); n (%); Median (IQR)
Show code
dataset %>%
  transmute(
    #"Age \u226565 years" = ifelse(Age >=65,1,0),
    "Age (years)" = Age,
    "Male sex" = ifelse(Sex == "M", "Yes","No"),
    "ECOG PS" = factor( recode(ECOG, "0"="0-1","1"="0-1","2"="\u22652","3"="\u22652","4"="\u22652"), levels = c("0-1", "\u22652") ),
    "HCT-CI" = HCT.CI,
    "TRANSCEND eligible" = TRANSCEND,
    "Second line" = Second.line,
    "Prior ASCT" = ASCT,
    #"Received bridging" = Bridging,
    "Bridging response category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD", "3" = "Unknown response"), levels = c("No bridging","CR/PR","SD/PD", "Unknown response")),
    "Disease subtype" = Disease,
    "LDH" = LDH.preLD,
    "ALC" = ALC.preLD,
    #"Elevated LDH (\u2265210 U/L)" = ifelse(LDH.preLD >=210,"Yes","No"),
    #"LDH status" = factor(recode(LDH.status, "0" = "\u2264ULN", "1" = "[ULN; 2x ULN]", "2"=">2x ULN"), levels = c("\u2264ULN", "[ULN; 2x ULN]", ">2x ULN") ),
    "Largest lesion (cm)" = Largest.lesion,
    #"Bulky (\u22655 cm)" = ifelse(Bulky == 1, "Yes","No"),
    "Extranodal" = ifelse(Extranodal == 1, "Yes","No"),
    "Out-of-specification" = ifelse(EAP == 1,"Yes","No"),
    "Product" = factor(recode(CAR.T.Product.Type, "Breyanzi"= "Liso-cel", "Yescarta" = "Axi-cel"), levels = c("Liso-cel","Axi-cel"))
  ) %>%
  tbl_summary(
    by = "Product",
    missing = "ifany",
    #sort = all_categorical() ~ "frequency",
    type = c("HCT-CI" = "continuous", "ECOG" = "continuous"),
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)",
      "Age (years)" ~"{median} ({min} to {max})"
    )
  ) %>%
  modify_spanning_header(all_stat_cols() ~ "**CAR-T Treatment**") %>%
  modify_header(all_stat_cols() ~ "**{level}**<br>N = {n} ({style_percent(p)}%)") %>%
  bold_labels %>%
  add_p() %>%
  add_stat_label()
Characteristic CAR-T Treatment p-value1
Liso-cel
N = 50 (34%)
Axi-cel
N = 99 (66%)
Age (years), Median (Range) 67 (45 to 83) 61 (26 to 79) <0.001
Male sex, n (%) 27 (54%) 66 (67%) 0.13
ECOG PS, n (%)

0.4
    0-1 42 (84%) 78 (79%)
    ≥2 8 (16%) 21 (21%)
HCT-CI, Median (IQR) 1.00 (1.00, 3.00) 1.00 (1.00, 3.00) >0.9
TRANSCEND eligible, n (%) 31 (62%) 71 (72%) 0.2
Second line, n (%) 8 (16%) 7 (7.1%) 0.087
Prior ASCT, n (%) 5 (10%) 19 (19%) 0.15
Bridging response category, n (%)

0.002
    No bridging 22 (44%) 66 (67%)
    CR/PR 11 (22%) 10 (10%)
    SD/PD 13 (26%) 23 (23%)
    Unknown response 4 (8.0%) 0 (0%)
Disease subtype, n (%)

0.4
    DLBCL 33 (66%) 71 (72%)
    HGBCL 3 (6.0%) 4 (4.0%)
    PMBCL 0 (0%) 5 (5.1%)
    TCHRLBCL 1 (2.0%) 1 (1.0%)
    tDLBCL 13 (26%) 18 (18%)
LDH, Median (IQR) 180 (151, 245) 206 (153, 308) 0.3
    Unknown 0 1
ALC, Median (IQR) 0.74 (0.44, 1.01) 0.57 (0.31, 0.96) 0.081
Largest lesion (cm), Median (IQR) 2.7 (0.2, 4.4) 3.4 (2.1, 6.6) 0.067
Extranodal, n (%) 28 (56%) 59 (60%) 0.7
Out-of-specification, n (%) 11 (22%) 2 (2.0%) <0.001
1 Wilcoxon rank sum test; Pearson’s Chi-squared test; Fisher’s exact test

IPTW weighted data table

Show code
theme_gtsummary_compact()
data1 = IPTW.data %>%
  mutate(
    "Age (years)" = Age,
    Male.sex = ifelse(Sex == "M", "Yes","No"),
    ECOG = factor( recode(ECOG, "0"="0-1","1"="0-1","2"="\u22652","3"="\u22652","4"="\u22652"), levels = c("0-1", "\u22652") ),
    Bridging = factor(recode(Bridging.response.category, "0"="No bridging","1"="CR/PR","2"="SD/PD","3"="Unknown response"), levels = c("No bridging","CR/PR","SD/PD", "Unknown response")),
    Product = factor(recode(CAR.T.Product.Type, "Breyanzi"= "Liso-cel", "Yescarta" = "Axi-cel"), levels = c("Liso-cel","Axi-cel")),
  )

  survey::svydesign(
    id = ~0,
    weights = ~weights,
    data = data1,
    fpc = NULL
  ) %>%
  tbl_svysummary(
    by = Product,
    missing = "ifany",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"),
    include = c(Age, Male.sex, ECOG, HCT.CI, TRANSCEND, Second.line, ASCT, Disease, LDH.preLD, ALC.preLD, Largest.lesion, Extranodal, Bridging, EAP),
    label = list(
      Male.sex ~ "Male sex",
      HCT.CI ~ "HCT-CI",
      Second.line ~ "Second line",
      LDH.preLD ~ "LDH",
      ALC.preLD ~ "ALC",
      Largest.lesion ~ "Largest lesion (cm)",
      Bridging ~ "Bridging response category"
    ),
  ) %>%
  add_p() %>%
    bold_labels()#%>%
Characteristic Liso-cel, N = 411 Axi-cel, N = 861 p-value2
Age 61 (52, 69) 64 (52, 68) 0.7
Male sex 24 (59%) 59 (69%) 0.3
ECOG

0.7
    0-1 31 (76%) 68 (79%)
    ≥2 10 (24%) 18 (21%)
HCT-CI 1.00 (1.00, 3.00) 1.00 (1.00, 3.00) 0.9
TRANSCEND 22 (55%) 63 (73%) 0.053
Second line 4 (8.7%) 9 (10%) 0.8
ASCT 5 (13%) 13 (16%) 0.7
Disease

0.7
    DLBCL 27 (67%) 59 (69%)
    HGBCL 2 (4.2%) 3 (3.2%)
    PMBCL 0 (0%) 3 (3.6%)
    TCHRLBCL 1 (1.8%) 1 (1.0%)
    tDLBCL 11 (27%) 20 (23%)
LDH 180 (151, 266) 190 (147, 297) 0.8
    Unknown 0 1
ALC 0.56 (0.38, 0.91) 0.54 (0.31, 0.97) 0.5
Largest lesion (cm) 3.3 (0.0, 5.2) 3.4 (2.1, 5.9) 0.5
Extranodal 25 (61%) 51 (59%) 0.8
Bridging response category

0.020
    No bridging 17 (42%) 55 (64%)
    CR/PR 8 (19%) 12 (14%)
    SD/PD 12 (30%) 18 (21%)
    Unknown response 3 (7.9%) 0 (0%)
EAP 9 (23%) 1 (1.6%) <0.001
1 Median (IQR); n (%)
2 Wilcoxon rank-sum test for complex survey samples; chi-squared test with Rao & Scott’s second-order correction
Show code
  #sort_p()

Reasons ineligible for TRANSCEND

Show code
data <- dataset %>%
  distinct() %>%
  filter(TRANSCEND == 0 & !is.na(Rationale.category) ) %>%
  count(Rationale.category) %>%
  mutate(
    pct = prop.table(n) * 100
    )

data %>%
  ggplot() +
  aes(x = "", y = pct, fill = reorder(Rationale.category, -pct)) +
  geom_col(position = 'stack', width = 1) +
  coord_polar("y") +
  xlab(NULL) +
  ylab(NULL) +
  theme_void() +
  scale_fill_brewer(palette = "Pastel2") +
  geom_text(aes(x = 1.3, label = paste0(sprintf("%1.f", pct), "%", "\u000A", "n=", n)), position = position_stack(vjust = 0.5), size = 5) +
  theme(axis.text.x = element_blank(),
        axis.ticks = element_blank(),
        legend.text = element_text(size = 16),
        legend.title = element_text(size = 16)) +  # Set legend title font size and make it bold
  labs(fill = paste0("Primary reason (N = ", tally(filter(dataset, TRANSCEND==0))$n, ")" ) )

Time to product infusion

Show code
theme_gtsummary_compact()

dataset %>%
  #filter(Largest.lesion !=0) %>% #only include measurable disease
  filter(Infused == 1) %>%
  transmute(
    "Product" = factor(recode(CAR.T.Product.Type, "Breyanzi"= "Liso-cel", "Yescarta" = "Axi-cel"), levels = c("Liso-cel","Axi-cel")),
    "Vein-to-vein time (days)" = Vein.to.vein.time,
    "Arrival-to-infusion time (days)" = Arrival.to.vein.time,
    "Order-to-infusion time (days)" = Order.to.vein.time,
    #"Total inpatient duration (days)" = inpatient.duration,
  ) %>%
  tbl_summary(
    by = "Product",
    missing = "no",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"
    )
  ) %>%
  bold_labels %>%
  add_p() %>%
  add_stat_label()
Characteristic Liso-cel, N = 50 Axi-cel, N = 99 p-value1
Vein-to-vein time (days), Median (IQR) 34 (32, 40) 27 (26, 30) <0.001
Arrival-to-infusion time (days), Median (IQR) 46 (42, 56) 40 (35, 45) <0.001
Order-to-infusion time (days), Median (IQR) 62 (44, 77) 34 (32, 41) <0.001
1 Wilcoxon rank sum test

Pre-LD lab values

Show code
theme_gtsummary_compact()

dataset %>%
  filter(LD == 1) %>%
  transmute(
    "Pre-LD WBC (10\U00B3/\U00B5L)" = WBC.preLD,
    "Pre-LD Plt (10\U00B3/\U00B5L)" = Plt.preLD,
    "Pre-LD Hgb (g/dL)" = Hgb.preLD,
    "Pre-LD ANC (10\U00B3/\U00B5L)" = ANC.preLD,
    "ALC pre-LD (10\U00B3/\U00B5L)" = ALC.preLD,
    "Pre-LD ferritin (ng/mL)" = ferritin.preLD,
    "Pre-LD cre (mg/dL)" = cre.preLD,
    "LDH pre-LD (U/L)" = LDH.preLD,
    "Product" = CAR.T.Product.Type,
  ) %>%
  tbl_summary(
    by = "Product",
    missing = "no",
    #sort = all_categorical() ~ "frequency",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"
    )
  ) %>%
  bold_labels %>%
  add_p() %>%
  sort_p() %>%
  add_stat_label()
Characteristic Breyanzi, N = 50 Yescarta, N = 99 p-value1
ALC pre-LD (10³/µL), Median (IQR) 0.74 (0.44, 1.01) 0.57 (0.31, 0.96) 0.081
Pre-LD Hgb (g/dL), Median (IQR) 11.30 (10.05, 12.32) 10.20 (9.60, 11.90) 0.10
LDH pre-LD (U/L), Median (IQR) 180 (151, 245) 206 (153, 308) 0.3
Pre-LD ferritin (ng/mL), Median (IQR) 266 (119, 672) 388 (174, 836) 0.4
Pre-LD cre (mg/dL), Median (IQR) 0.84 (0.66, 1.01) 0.87 (0.70, 1.04) 0.6
Pre-LD ANC (10³/µL), Median (IQR) 2.67 (2.06, 4.21) 3.00 (1.61, 4.97) 0.6
Pre-LD Plt (10³/µL), Median (IQR) 149 (114, 199) 160 (99, 203) 0.8
Pre-LD WBC (10³/µL), Median (IQR) 4.2 (3.4, 6.3) 4.7 (3.0, 6.6) >0.9
1 Wilcoxon rank sum test

Admission characteristics

Show code
theme_gtsummary_compact()

dataset %>%
  filter(Infused == 1) %>%
  transmute(
    "Product" = CAR.T.Product.Type,
    "Vein-to-vein time (days)" = Vein.to.vein.time,
    "Order-to-vein time (days)" = Order.to.vein.time,
    "Arrival-to-vein time (days)" = Arrival.to.vein.time,
    "# of admissions" = admissions,
    '2+ admissions' = ifelse(admissions>=2, 1, 0),
    "Elective admission" = recode(elective.admission, "1" = "Yes", "0" = "No"),
    "Total inpatient duration (days)" = inpatient.duration,
    "Elective duration (days)" = elective.duration,
    "Non-elective duration (days)" = inpatient.duration - elective.duration,
  ) %>%
  tbl_summary(
    by = "Product",
    missing = "no",
    #sort = all_categorical() ~ "frequency",
    type = c("Elective duration (days)" ~ "continuous"),
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)",
      "Elective duration (days)" ~ "{median} ({min} to {max})",
      "Non-elective duration (days)" ~ "{median} ({min} to {max})",
      "Total inpatient duration (days)" ~ "{median} ({min} to {max})"
    )
  ) %>%
  bold_labels %>%
  add_p() %>%
  add_stat_label()
Characteristic Breyanzi, N = 50 Yescarta, N = 99 p-value1
Vein-to-vein time (days), Median (IQR) 34 (32, 40) 27 (26, 30) <0.001
Order-to-vein time (days), Median (IQR) 62 (44, 77) 34 (32, 41) <0.001
Arrival-to-vein time (days), Median (IQR) 46 (42, 56) 40 (35, 45) <0.001
# of admissions, n (%)

<0.001
    0 19 (38%) 9 (9.1%)
    1 27 (54%) 69 (70%)
    2 2 (4.0%) 18 (18%)
    3 2 (4.0%) 3 (3.0%)
2+ admissions, n (%) 4 (8.0%) 21 (21%) 0.042
Elective admission, n (%) 5 (10%) 82 (83%) <0.001
Total inpatient duration (days), Median (Range) 5 (0 to 35) 14 (0 to 54) <0.001
Elective duration (days), Median (Range) 0 (0 to 30) 12 (0 to 48) <0.001
Non-elective duration (days), Median (Range) 2.5 (0.0 to 35.0) 0.0 (0.0 to 54.0) 0.006
1 Wilcoxon rank sum test; Fisher’s exact test; Pearson’s Chi-squared test

Vein-to-vein histogram

Show code
Median_breyanzi_vv = signif(median(as.numeric(filter(dataset, CAR.T.Product.Type == "Breyanzi")$Vein.to.vein.time)), 2)
Median_yescarta_vv = signif(median(as.numeric(filter(dataset, CAR.T.Product.Type == "Yescarta")$Vein.to.vein.time)), 2)

histogram_vv <- dataset %>%
  mutate(CAR.T.Product.Type = recode(CAR.T.Product.Type,"Breyanzi" = "Liso-cel","Yescarta" = "Axi-cel")) %>%
  ggplot( aes(x=as.numeric(Vein.to.vein.time), fill=CAR.T.Product.Type) )  +
    geom_histogram( color="#e9ecef", alpha=0.6, position = 'identity', binwidth=7) +
    scale_fill_manual(values = c("#69b3a2", "#404080"), guide = "none") +  # Remove the legend
    theme_classic() +
    labs(fill="") + 
  geom_vline(aes(xintercept = Median_yescarta_vv),
             linetype = "dashed", color = "#69b3a2", linewidth = 0.75)+ 
  geom_vline(aes(xintercept = Median_breyanzi_vv),
             linetype = "dashed", color = "#404080", linewidth = 0.75) +
  xlim(10, 70)+
  xlab("Vein-to-vein time (days)") + 
  ylab("Number of patients") + 
  annotate("text", label=Median_yescarta_vv, x = Median_yescarta_vv +3, y = 61, color = "#69b3a2") + 
  annotate("text", label=Median_breyanzi_vv, x = Median_breyanzi_vv +3, y = 61, color = "#404080") + 
  theme(legend.position = c(0.8, 0.8)) + 
  theme(
    axis.title = element_text(size = 16),
    axis.text = element_text(size = 16),
    legend.title = element_text(size = 16),
    legend.text = element_text(size = 14)
  ) + 
    annotate("text", x = 45, y = 55, label = sprintf("p <.001"), size = 5)
histogram_vv

Age histogram

Show code
Median_breyanzi_age = signif(median(as.numeric(filter(dataset, CAR.T.Product.Type == "Breyanzi")$Age)), 2)
Median_yescarta_age = signif(median(as.numeric(filter(dataset, CAR.T.Product.Type == "Yescarta")$Age)), 2)

histogram_age <- dataset %>%
  mutate(CAR.T.Product.Type = recode(CAR.T.Product.Type,"Breyanzi" = "Liso-cel","Yescarta" = "Axi-cel")) %>%
  ggplot( aes(x=as.numeric(Age), fill=CAR.T.Product.Type) )  +
    geom_histogram( color="#e9ecef", alpha=0.6, position = 'identity', binwidth=5) +
    scale_fill_manual(values=c("#69b3a2", "#404080")) +
    theme_classic() +
    labs(fill="") + 
  geom_vline(aes(xintercept = Median_yescarta_age),
             linetype = "dashed", color = "#69b3a2", linewidth = 0.75)+ 
  geom_vline(aes(xintercept = Median_breyanzi_age),
             linetype = "dashed", color = "#404080", linewidth = 0.75) +
  xlim(20, 90)+
  xlab("Age (years)") + 
  ylab("Number of patients") + 
  annotate("text", label=Median_yescarta_age, x = Median_yescarta_age +3, y = 22, color = "#69b3a2") + 
  annotate("text", label=Median_breyanzi_age, x = Median_breyanzi_age +3, y = 22, color = "#404080") + 
  theme(legend.position = c(0.87, 0.8)) + 
  theme(
    axis.title = element_text(size = 16),
    axis.text = element_text(size = 16),
    legend.title = element_text(size = 16),
    legend.text = element_text(size = 12)
  ) + 
    annotate("text", x = 50, y = 20, label = sprintf("p <.001"), size = 5)
histogram_age

Combined histogram

Show code
ggarrange(histogram_vv, histogram_age, ncol = 2, labels = c("A", "B"))

Table for response

Show code
theme_gtsummary_compact()

data1 <- dataset %>%
  mutate(
    CAR.T.Product.Type = recode(CAR.T.Product.Type, "Breyanzi" = "Liso-cel","Yescarta" = "Axi-cel")
  )

tbl1 <- data1 %>%
  filter(Infused == 1) %>%
  filter(Response.evaluable ==1) %>% #only include measurable disease
  transmute(
    "Product" = CAR.T.Product.Type,
    "Initial response" = Initial.response,
    "Best response" = Best.response,
    "Progressive disease" = recode(Best.PD,"0"="No","1"="Yes"),
    "ORR" = ifelse(Best.response == "CR" | Best.response == "PR",1,0)
  ) %>%
  tbl_summary(
    by = "Product",
    missing = "no",
    #sort = all_categorical() ~ "frequency",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"
    )
  ) %>%
  bold_labels %>%
  add_p() %>%
  add_stat_label()

tbl2 <- data1 %>%
  filter(Infused == 1) %>%
  transmute(
    "Product" = CAR.T.Product.Type,
    "Initial response" = Initial.response,
    "Best response" = Best.response,
    "Progressive disease" = recode(Best.PD,"0"="No","1"="Yes"),
    "ORR" = ifelse(Best.response == "CR" | Best.response == "PR",1,0)
  ) %>%
  tbl_summary(
    by = "Product",
    missing = "no",
    #sort = all_categorical() ~ "frequency",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"
    )
  ) %>%
  bold_labels %>%
  add_p() %>%
  add_stat_label()

tbl_merge(
  tbls = list(tbl1, tbl2),                          # combine
  tab_spanner = c("**Response evaluable**", "**All patients**")) # set header names
Characteristic Response evaluable All patients
Axi-cel, N = 95 Liso-cel, N = 41 p-value1 Axi-cel, N = 99 Liso-cel, N = 50 p-value1
Initial response, n (%)

0.7

>0.9
    CR 39 (41%) 13 (32%)
42 (42%) 22 (44%)
    PD 21 (22%) 10 (24%)
22 (22%) 10 (20%)
    PR 33 (35%) 17 (41%)
33 (33%) 17 (34%)
    SD 2 (2.1%) 1 (2.4%)
2 (2.0%) 1 (2.0%)
Best response, n (%)

>0.9

0.7
    CR 45 (47%) 20 (49%)
48 (48%) 29 (58%)
    PD 21 (22%) 10 (24%)
22 (22%) 10 (20%)
    PR 28 (29%) 11 (27%)
28 (28%) 11 (22%)
    SD 1 (1.1%) 0 (0%)
1 (1.0%) 0 (0%)
Progressive disease, n (%) 21 (22%) 10 (24%) 0.8 22 (22%) 10 (20%) 0.8
ORR, n (%) 73 (77%) 31 (76%) 0.9 76 (77%) 40 (80%) 0.7
1 Fisher’s exact test; Pearson’s Chi-squared test

IPTW weighted response table

Show code
theme_gtsummary_compact()
data1 = IPTW.data %>%
  transmute(
    "Product" = recode(CAR.T.Product.Type, "Breyanzi"="Liso-cel","Yescarta"="Axi-cel"),
    "Initial response" = Initial.response,
    "Best response" = Best.response,
    "Progressive disease" = as.factor( recode(Best.PD,"0"="No","1"="Yes") ),
    "ORR" = ifelse(Best.response == "CR" | Best.response == "PR",1,0),
    weights,
    Response.evaluable
  )


tbl1<-  survey::svydesign(
    id = ~0,
    weights = ~weights,
    data = filter(data1, Response.evaluable==1), # Only include measurable disease
    fpc = NULL
  ) %>%
  tbl_svysummary(
    by = Product,
    missing = "ifany",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"),
    include = c("Initial response", "Best response", "Progressive disease", "ORR")
  ) %>%
  bold_labels() %>%
  add_p()

tbl2<-  survey::svydesign(
    id = ~0,
    weights = ~weights,
    data = data1, # Include response evaluable and all patients
    fpc = NULL
  ) %>%
  tbl_svysummary(
    by = Product,
    missing = "ifany",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"),
    include = c("Initial response", "Best response", "Progressive disease", "ORR")
  ) %>%
  bold_labels() %>%
  add_p()
  
  
tbl_merge(
  tbls = list(tbl1, tbl2),                          # combine
  tab_spanner = c("**Response evaluable**", "**All patients**")) # set header names
Characteristic Response evaluable All patients
Axi-cel, N = 821 Liso-cel, N = 341 p-value2 Axi-cel, N = 861 Liso-cel, N = 411 p-value2
Initial response

0.7

0.8
    CR 36 (44%) 12 (34%)
38 (44%) 18 (45%)
    PD 18 (22%) 7 (21%)
20 (24%) 7 (17%)
    PR 26 (32%) 14 (43%)
26 (31%) 14 (36%)
    SD 1 (1.8%) 1 (2.8%)
1 (1.7%) 1 (2.4%)
Best response

>0.9

0.6
    CR 41 (50%) 18 (52%)
43 (50%) 24 (60%)
    PD 18 (22%) 7 (21%)
20 (24%) 7 (17%)
    PR 22 (27%) 9 (27%)
22 (26%) 9 (23%)
    SD 1 (1.0%) 0 (0%)
1 (1.0%) 0 (0%)
Progressive disease 18 (22%) 7 (21%) 0.8 20 (24%) 7 (17%) 0.4
ORR 63 (77%) 27 (79%) 0.7 65 (75%) 34 (83%) 0.3
1 n (%)
2 chi-squared test with Rao & Scott’s second-order correction

Table for toxicity

Show code
theme_gtsummary_compact()

dataset %>%
  filter(Infused == 1) %>%
  transmute(
    "Product" = CAR.T.Product.Type,
    #"Max CRS grade" = CRS.grade,
    "CRS any grade" = ifelse( CRS.grade != 0, 1, 0),
    "CRS grade 3-4" = ifelse( CRS.grade ==3 | CRS.grade == 4, 1, 0),
    "Time to CRS (days)" = CRS.day,
    #"Max ICANS grade" = ICANS.grade,
    "ICANS any grade" = ifelse( ICANS.grade != 0,1,0),
    "ICANS grade 3-4" = ifelse( ICANS.grade ==3 | ICANS.grade == 4,1,0),
    "Days with fever" = fever.days,
    "Fever 1st day" = fever.first.day,
    "Time to ICANS (days)" = ICANS.day,
    "Toci doses" = toci.doses,
    "Received toci" = ifelse(toci.doses !=0,1,0),
    "Dex doses" = dex.doses,
    "Received dex" = ifelse(dex.doses !=0,1,0),
    "ICE score min" = ICE.min
  ) %>%
  tbl_summary(
    by = "Product",
    missing = "no",
    #sort = all_categorical() ~ "frequency",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"
      #"Time to ICANS (days)" ~ "{median} ({min}, {max})"
    ),
    type = list("Toci doses" ~ "continuous", "ICE score min" ~ "continuous", "Dex doses" ~ "continuous", "Time to ICANS (days)" ~ "continuous")
  ) %>%
  bold_labels %>%
  add_p() %>%
  add_stat_label()
Characteristic Breyanzi, N = 50 Yescarta, N = 99 p-value1
CRS any grade, n (%) 32 (64%) 88 (89%) <0.001
CRS grade 3-4, n (%) 1 (2.0%) 8 (8.1%) 0.3
Time to CRS (days), Median (IQR) 4.00 (2.00, 6.00) 4.00 (2.00, 6.00) >0.9
ICANS any grade, n (%) 14 (28%) 52 (53%) 0.004
ICANS grade 3-4, n (%) 9 (18%) 18 (18%) >0.9
Days with fever, Median (IQR) 3 (2, 4) 5 (3, 7) <0.001
Fever 1st day, Median (IQR) 3.00 (1.50, 5.00) 3.00 (1.00, 5.00) 0.7
Time to ICANS (days), Median (IQR) 7.0 (7.0, 8.8) 7.0 (5.0, 9.3) 0.4
Toci doses, Median (IQR) 0.00 (0.00, 0.00) 1.00 (0.00, 1.00) <0.001
Received toci, n (%) 12 (24%) 53 (54%) <0.001
Dex doses, Median (IQR) 0 (0, 5) 2 (0, 13) 0.001
Received dex, n (%) 16 (32%) 65 (66%) <0.001
ICE score min, Median (IQR) 10.0 (6.0, 10.0) 8.0 (3.0, 10.0) 0.013
1 Pearson’s Chi-squared test; Fisher’s exact test; Wilcoxon rank sum test

IPTW weighted toxicity table

Show code
theme_gtsummary_compact()
data1 = IPTW.data %>%
  transmute(
    "Product" = recode(CAR.T.Product.Type, "Breyanzi"="Liso-cel","Yescarta"="Axi-cel"),
    #"Max CRS grade" = CRS.grade,
    "CRS any grade" = ifelse( CRS.grade != 0, 1, 0),
    "CRS grade 3-4" = ifelse( CRS.grade ==3 | CRS.grade == 4, 1, 0),
    "Time to CRS (days)" = CRS.day,
    #"Max ICANS grade" = ICANS.grade,
    "ICANS any grade" = ifelse( ICANS.grade != 0,1,0),
    "ICANS grade 3-4" = ifelse( ICANS.grade ==3 | ICANS.grade == 4,1,0),
    "Days with fever" = fever.days,
    "Fever 1st day" = fever.first.day,
    "Time to ICANS (days)" = ICANS.day,
    "Toci doses" = as.numeric(toci.doses),
    "Received toci" = ifelse(toci.doses !=0,1,0),
    "Dex doses" = as.numeric(dex.doses),
    "Received dex" = ifelse(dex.doses !=0,1,0),
    "ICE score min" = ICE.min,
    weights
  )


survey::svydesign(
    id = ~0,
    weights = ~weights,
    data = data1,
    fpc = NULL
  ) %>%
  tbl_svysummary(
    by = Product,
    missing = "no",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"),
    include = c("CRS any grade","CRS grade 3-4","ICANS any grade","ICANS grade 3-4")
  ) %>%
  bold_labels %>%
  add_p()
Characteristic Axi-cel, N = 861 Liso-cel, N = 411 p-value2
CRS any grade 73 (85%) 27 (67%) 0.040
CRS grade 3-4 7 (7.8%) 1 (3.0%) 0.3
ICANS any grade 43 (50%) 15 (36%) 0.2
ICANS grade 3-4 14 (17%) 10 (25%) 0.3
1 n (%)
2 chi-squared test with Rao & Scott’s second-order correction

Table for ID complications

Show code
theme_gtsummary_compact()

dataset %>%
  transmute(
    "Product" = CAR.T.Product.Type,
    "Positive BCx" = Pos.BCx,
    "Positive CMV" = CMV,
    "CMV level detectable" = ifelse(CMV.peak.level >0, 1, 0),
    "CMV duration" = CMV.last.day - CMV.first.day,
    "Cefepime doses" = cefepime.doses,
    "Received cefepime" = ifelse(cefepime.doses >=1,1,0),
    "Vancomycin doses" = vancomycin.doses
  ) %>%
  tbl_summary(
    by = "Product",
    missing = "no",
    #sort = all_categorical() ~ "frequency",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"
    )
  ) %>%
  bold_labels %>%
  add_p() %>%
  add_stat_label() %>%
  sort_p()
Characteristic Breyanzi, N = 50 Yescarta, N = 99 p-value1
Cefepime doses, Median (IQR) 0 (0, 8) 9 (0, 16) <0.001
Received cefepime, n (%) 21 (42%) 68 (69%) 0.002
Vancomycin doses, Median (IQR) 0.0 (0.0, 0.0) 0.0 (0.0, 3.0) 0.3
Positive BCx, n (%) 2 (4.0%) 8 (8.1%) 0.5
CMV level detectable, n (%) 6 (12%) 9 (9.1%) 0.6
Positive CMV, n (%) 15 (30%) 26 (26%) 0.6
CMV duration, Median (IQR) 19 (4, 26) 14 (7, 34) 0.8
1 Fisher’s exact test; Pearson’s Chi-squared test; Wilcoxon rank sum test

Table for post-infusion cytopenias

Show code
theme_gtsummary_compact()

data1 <- dataset %>%
  mutate(
    CAR.T.Product.Type = recode(CAR.T.Product.Type,"Breyanzi"="Liso-cel","Yescarta"="Axi-cel")
  )

data1 %>%
  filter(Infused == 1) %>%
  transmute(
    "Product" = CAR.T.Product.Type,
    "WBC min (10\U00B3/\U00B5L)" = WBC.min,
    "WBC nadir day" = WBC_day_nadir,
    "ANC min (10\U00B3/\U00B5L)" = ANC.min,
    "ANC <500 (cells/\U00B5L)" = ifelse(ANC.min <0.5, "Yes","No"),
    "Hgb min (g/dL)" = Hgb.min,
    "Plt min (10\U00B3/\U00B5L)" = Plt.min,
    "Neutropenic time (days)" = neutropenic.days
  ) %>%
  tbl_summary(
    by = "Product",
    missing = "no",
    #sort = all_categorical() ~ "frequency",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"
    )
  ) %>%
  bold_labels %>%
  add_p() %>%
  add_stat_label() %>%
  sort_p()
Characteristic Axi-cel, N = 99 Liso-cel, N = 50 p-value1
ANC min (10³/µL), Median (IQR) 0.04 (0.00, 0.17) 0.26 (0.10, 0.51) <0.001
WBC min (10³/µL), Median (IQR) 0.25 (0.14, 0.48) 0.65 (0.37, 1.38) <0.001
Neutropenic time (days), Median (IQR) 6.0 (3.0, 10.0) 2.0 (0.3, 5.0) <0.001
Hgb min (g/dL), Median (IQR) 8.20 (7.75, 8.85) 8.80 (8.25, 10.10) 0.001
ANC <500 (cells/µL), n (%) 92 (93%) 37 (74%) 0.001
Plt min (10³/µL), Median (IQR) 36 (18, 67) 82 (32, 109) 0.002
WBC nadir day, Median (IQR) 4.0 (3.0, 6.0) 5.0 (3.0, 6.8) 0.4
1 Wilcoxon rank sum test; Pearson’s Chi-squared test

Table for day 30 counts

Show code
theme_gtsummary_compact()

data1 <- dataset %>%
  mutate(
    CAR.T.Product.Type = recode(CAR.T.Product.Type,"Breyanzi"="Liso-cel","Yescarta"="Axi-cel")
  )

data1 %>%
  transmute(
    "Product" = CAR.T.Product.Type,
    "WBC d30 (10\U00B3/\U00B5L)" = WBC.30,
    "ANC d30 (10\U00B3/\U00B5L)" = ANC.30,
    "ALC d30 (10\U00B3/\U00B5L)" = ALC.30,
    "ANC <500 (cells/\U00B5L)" = ifelse(ANC.30 <0.5, "Yes","No"),
    "Hgb d30 (g/dL)" = Hgb.30,
    "Plt d30 (10\U00B3/\U00B5L)" = Plt.30,
  ) %>%
  tbl_summary(
    by = "Product",
    missing = "no",
    #sort = all_categorical() ~ "frequency",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"
    )
  ) %>%
  bold_labels %>%
  add_p() %>%
  add_stat_label() %>%
  sort_p()
Characteristic Axi-cel, N = 99 Liso-cel, N = 50 p-value1
Plt d30 (10³/µL), Median (IQR) 63 (33, 117) 102 (48, 145) 0.049
ANC d30 (10³/µL), Median (IQR) 1.38 (0.78, 2.31) 1.72 (1.15, 2.95) 0.14
WBC d30 (10³/µL), Median (IQR) 2.59 (1.53, 3.73) 2.90 (2.12, 4.07) 0.4
ANC <500 (cells/µL), n (%) 14 (15%) 5 (10%) 0.5
ALC d30 (10³/µL), Median (IQR) 0.47 (0.24, 0.95) 0.48 (0.33, 0.63) 0.5
Hgb d30 (g/dL), Median (IQR) 10.40 (9.40, 11.55) 10.50 (9.95, 11.20) 0.6
1 Wilcoxon rank sum test; Pearson’s Chi-squared test

Table for post-infusion inflammatory markers and other labs

Show code
theme_gtsummary_compact()

dataset %>%
  mutate(
    CAR.T.Product.Type = recode(CAR.T.Product.Type,"Breyanzi"="Liso-cel","Yescarta"="Axi-cel")
  ) %>%
  transmute(
    "Product" = CAR.T.Product.Type,
    "ALT max (U/L)" = ALT.max,
    "AST max (U/L)" = AST.max,
    "CRP max (mg/L)" = CRP.max,
    "D-dimer max (mg/L)" = ddimer.max,
    "Ferritin max (ng/mL)" = ferritin.max,
    "IL6 max (pg/mL)" = IL6.max,
    "LDH max (U/L)" = LDH.max
  ) %>%
  tbl_summary(
    by = "Product",
    missing = "no",
    #sort = all_categorical() ~ "frequency",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"
    )
  ) %>%
  bold_labels %>%
  add_p() %>%
  add_stat_label() %>%
  sort_p()
Characteristic Axi-cel, N = 99 Liso-cel, N = 50 p-value1
CRP max (mg/L), Median (IQR) 118 (57, 180) 63 (9, 114) <0.001
IL6 max (pg/mL), Median (IQR) 207 (58, 1,165) 55 (15, 481) 0.001
ALT max (U/L), Median (IQR) 53 (36, 82) 30 (22, 67) 0.004
D-dimer max (mg/L), Median (IQR) 2.5 (1.5, 3.9) 1.4 (0.7, 3.3) 0.007
Ferritin max (ng/mL), Median (IQR) 1,217 (488, 2,520) 783 (206, 1,709) 0.017
AST max (U/L), Median (IQR) 36 (27, 60) 28 (22, 49) 0.073
LDH max (U/L), Median (IQR) 250 (189, 355) 215 (176, 346) 0.2
1 Wilcoxon rank sum test

Table for post-infusion inflammatory markers and other labs, stratified by product and CRS

Show code
theme_gtsummary_compact()

dataset %>%
  mutate(
    CAR.T.Product.Type = recode(CAR.T.Product.Type, "Breyanzi" = "Liso-cel", "Yescarta" = "Axi-cel")
  ) %>%
  transmute(
    "ALT max (U/L)" = ALT.max,
    "AST max (U/L)" = AST.max,
    "CRP max (mg/L)" = CRP.max,
    "D-dimer max (mg/L)" = ddimer.max,
    "Ferritin max (ng/mL)" = ferritin.max,
    "IL6 max (pg/mL)" = IL6.max,
    "LDH max (U/L)" = LDH.max,
    CRS.grade = recode(CRS.grade, "0" = "0", "1" = "1-2", "2" = "1-2", "3" = "3+", "4" = "3+")
  ) %>%
  tbl_summary(
    by = CRS.grade,
    missing = "no",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"
    )
  ) %>%
  modify_spanning_header(all_stat_cols() ~ "**CRS grade**") %>%
  modify_header(all_stat_cols() ~ "**{level}**<br>N = {n} ({style_percent(p)}%)") %>%
  bold_labels() %>%
  add_p() %>%
  add_stat_label()
Characteristic CRS grade p-value1
0
N = 29 (19%)
1-2
N = 111 (74%)
3+
N = 9 (6.0%)
ALT max (U/L), Median (IQR) 23 (20, 31) 57 (33, 85) 68 (44, 158) <0.001
AST max (U/L), Median (IQR) 23 (20, 30) 36 (27, 58) 57 (42, 83) <0.001
CRP max (mg/L), Median (IQR) 18 (6, 45) 114 (62, 168) 160 (123, 203) <0.001
D-dimer max (mg/L), Median (IQR) 1.0 (0.6, 2.5) 2.3 (1.4, 3.7) 9.2 (8.1, 15.1) <0.001
Ferritin max (ng/mL), Median (IQR) 283 (174, 491) 1,217 (556, 2,113) 11,312 (8,863, 14,982) <0.001
IL6 max (pg/mL), Median (IQR) 20 (13, 54) 174 (56, 739) 7,125 (3,064, 21,316) <0.001
LDH max (U/L), Median (IQR) 175 (151, 226) 250 (193, 351) 708 (594, 1,163) <0.001
1 Kruskal-Wallis rank sum test
Show code
dataset %>%
  mutate(
    CAR.T.Product.Type = recode(CAR.T.Product.Type, "Breyanzi" = "Liso-cel", "Yescarta" = "Axi-cel")
  ) %>%
  transmute(
    "ALT max (U/L)" = ALT.max,
    "AST max (U/L)" = AST.max,
    "CRP max (mg/L)" = CRP.max,
    "D-dimer max (mg/L)" = ddimer.max,
    "Ferritin max (ng/mL)" = ferritin.max,
    "IL6 max (pg/mL)" = IL6.max,
    "LDH max (U/L)" = LDH.max,
    ICANS.grade = recode(ICANS.grade, "0" = "0", "1" = "1-2", "2" = "1-2", "3" = "3+", "4" = "3+")
  ) %>%
  tbl_summary(
    by = ICANS.grade,
    missing = "no",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"
    )
  ) %>%
  modify_spanning_header(all_stat_cols() ~ "**ICANS grade**") %>%
  modify_header(all_stat_cols() ~ "**{level}**<br>N = {n} ({style_percent(p)}%)") %>%
  bold_labels() %>%
  add_p() %>%
  add_stat_label()
Characteristic ICANS grade p-value1
0
N = 83 (56%)
1-2
N = 39 (26%)
3+
N = 27 (18%)
ALT max (U/L), Median (IQR) 31 (23, 58) 62 (41, 88) 89 (52, 158) <0.001
AST max (U/L), Median (IQR) 27 (21, 39) 44 (34, 59) 70 (31, 93) <0.001
CRP max (mg/L), Median (IQR) 62 (19, 116) 123 (66, 191) 148 (110, 198) <0.001
D-dimer max (mg/L), Median (IQR) 1.6 (0.8, 2.6) 2.5 (1.6, 3.7) 6.2 (3.3, 11.6) <0.001
Ferritin max (ng/mL), Median (IQR) 530 (261, 1,327) 1,619 (868, 2,579) 4,174 (1,631, 9,710) <0.001
IL6 max (pg/mL), Median (IQR) 54 (23, 154) 223 (111, 1,168) 1,454 (686, 5,459) <0.001
LDH max (U/L), Median (IQR) 218 (165, 280) 231 (189, 391) 357 (248, 623) <0.001
1 Kruskal-Wallis rank sum test

Table for cardiac/BP results

Show code
theme_gtsummary_compact()

dataset %>%
  mutate(
    CAR.T.Product.Type = recode(CAR.T.Product.Type,"Breyanzi"="Liso-cel","Yescarta"="Axi-cel")
  ) %>%
  transmute(
    "Product" = CAR.T.Product.Type,
    "Pre-LD SBP (mmHg)" = SBP.preLD,
    "Pre-LD DBP (mmHg)" = DBP.preLD,
    "Pre-LD MAP (mmHg)" = MAP.preLD,
    "Max SBP drop (mmHg)" = SBP.preLD - SBP.min,
    "Max DBP drop (mmHg)" = DBP.preLD - DBP.min,
    "Max MAP drop (mmHg)" = MAP.preLD - MAP.min,
    "Positive troponin (\u22650.03 ng/mL)" = ifelse(!is.na(trop.max) & trop.max >=0.03,1,0) 
  ) %>%
  tbl_summary(
    by = "Product",
    missing = "no",
    #sort = all_categorical() ~ "frequency",
    statistic = list(
      all_continuous() ~ "{median} ({p25}, {p75})",
      all_categorical() ~ "{n} ({p}%)"
    )
  ) %>%
  bold_labels %>%
  add_p() %>%
  add_stat_label() %>%
  sort_p()
Characteristic Axi-cel, N = 99 Liso-cel, N = 50 p-value1
Max DBP drop (mmHg), Median (IQR) 27 (20, 34) 20 (14, 25) <0.001
Max MAP drop (mmHg), Median (IQR) 29 (23, 36) 23 (17, 28) <0.001
Max SBP drop (mmHg), Median (IQR) 35 (28, 45) 27 (19, 37) 0.001
Pre-LD SBP (mmHg), Median (IQR) 116 (108, 127) 116 (111, 123) 0.6
Positive troponin (≥0.03 ng/mL), n (%) 4 (4.0%) 3 (6.0%) 0.7
Pre-LD MAP (mmHg), Median (IQR) 87 (81, 95) 88 (83, 94) 0.8
Pre-LD DBP (mmHg), Median (IQR) 74 (67, 80) 74 (69, 77) 0.8
1 Wilcoxon rank sum test; Fisher’s exact test

STACKED BAR GRAPH

Stacked bar graph of toxicity for liso-cel and axi-cel

Show code
combined_data <- rbind(
  dataset %>%
    count(CAR.T.Product.Type, CRS.grade) %>%
    group_by(CAR.T.Product.Type) %>%
    mutate(
      total = sum(n[CRS.grade != 0]),
      pct = prop.table(n) * 100,
      total_pct = sum(pct[CRS.grade != 0]),
      Grade = factor(CRS.grade, levels = c(0, 4, 3, 2, 1)),
      CAR.T.Product.Type = recode(CAR.T.Product.Type, "Breyanzi" = "Liso-cel", "Yescarta" = "Axi-cel"),
      Category = "CRS"
    ),
  dataset %>%
    count(CAR.T.Product.Type, ICANS.grade) %>%
    group_by(CAR.T.Product.Type) %>%
    mutate(
      total = sum(n[ICANS.grade != 0]),
      pct = prop.table(n) * 100,
      total_pct = sum(pct[ICANS.grade != 0]),
      Grade = factor(ICANS.grade, levels = c(0, 4, 3, 2, 1)),
      CAR.T.Product.Type = recode(CAR.T.Product.Type, "Breyanzi" = "Liso-cel", "Yescarta" = "Axi-cel"),
      Category = "ICANS"
    )
)

ggplot(combined_data) +
  aes(x = CAR.T.Product.Type, y = pct, fill = Grade) +
  geom_bar(stat = "identity", position = "stack", data = . %>% filter(Grade != 0)) +
    geom_text(aes(label = paste0(sprintf("%1.1f", pct), "% (",n,")")), 
            data = . %>% filter(Grade != 0),
            position = position_stack(vjust = 0.5)) + 
  geom_text( aes(label = paste0(sprintf("%1.1f", total_pct), "% (",total,")"), x = CAR.T.Product.Type, y = total_pct + 7, vjust = 0), 
             data = . %>% filter(Grade != 0),
             color = "#104a8e") +
  #geom_text(aes(label = paste0(sprintf("%1.1f", pct), "% (", n, ")")), position = position_dodge(width = 0.9), vjust = 0.5) +
  #geom_text(aes(label = paste0(sprintf("%1.1f", total_pct), "% (", total, ")"), y = total_pct + 7), color = "#104a8e") +
  facet_wrap(~Category, scales = "free_y") +
  ylab("Proportion of patients (%)") +
  xlab(NULL) +
  #ggtitle("Comparison of CRS and ICANS grades") +
  theme_classic()+
  scale_fill_brewer(palette = "Pastel1") +
  scale_y_continuous(breaks = seq(0, 100, by = 20), limits = c(0, 100)) +
  theme(
    axis.title = element_text(size = 16),
    axis.text = element_text(size = 16),
    legend.title = element_text(size = 16),
    legend.text = element_text(size = 14),
    axis.text.x = element_text(angle = 45, hjust = 1)
  )

COMPETING RISK ANALYSIS

Cumulative incidence of death

Show code
theme_gtsummary_compact()

data1 <- filter(dataset, Infused == 1) %>%
  select(Days.to.DLC, Alive.RM.NRM, CAR.T.Product.Type, Age, Largest.lesion, ALC.preLD, HCT.CI, LDH.preLD) %>%
  mutate(
   Alive.RM.NRM = as.factor(recode(Alive.RM.NRM,"0"="Alive","1"="Death from cancer","2"="Death from other causes")),
   CAR.T.Product.Type = factor(recode(CAR.T.Product.Type, "Breyanzi" = "Liso-cel", "Yescarta" = "Axi-cel"), levels = c("Liso-cel","Axi-cel") ),
   Months.to.DLC = Days.to.DLC/30
  )

cum <- tidycmprsk::cuminc(Surv( Months.to.DLC , Alive.RM.NRM) ~ CAR.T.Product.Type, data1, rho=0, conf.level=0.95)

cum %>%
  ggcuminc(
   #risk.table=TRUE,
   theme = theme_classic(),
   outcome = c("Death from cancer","Death from other causes")
  ) +
  labs(
    x = "Time (months)",
    y = "Probability of death"
  ) +
  ylim(0,1) +
  scale_x_continuous(breaks = seq(0, 36, by = 6), limits=c(0, 36)) +
  #add_confidence_interval() + 
  add_risktable(
    size = 5,
    risktable_stats = c("n.risk"),
    risktable_height = 0.2,
    stats_label = c("Number at risk"),
    theme = theme_risktable_default(axis.text.y.size = 14, plot.title.size = 14)
  )+ 
  add_pvalue() + 
  theme(
    legend.position =  c(0.22, 0.8),
    text = element_text(size = 16)  # Set text size to 16
  )
Show code
cum %>%
  tbl_cuminc(
    times = c(12),
    outcomes = c("Death from cancer","Death from other causes"),
    label_header = c("**{time}-month cuminc**")
  ) %>%
  add_p()
Characteristic 12-month cuminc p-value1
Death from cancer
CAR.T.Product.Type
0.5
    Liso-cel 27% (14%, 42%)
    Axi-cel 39% (28%, 50%)
Death from other causes
CAR.T.Product.Type
>0.9
    Liso-cel 7.3% (1.8%, 18%)
    Axi-cel 5.2% (1.7%, 12%)
1 Gray’s Test
Show code
uv_tab<-crr(Surv(Days.to.DLC, Alive.RM.NRM) ~ CAR.T.Product.Type, data = data1) %>%
  tbl_regression(exp = TRUE)

mv_tab<-crr(Surv(Days.to.DLC, Alive.RM.NRM) ~ CAR.T.Product.Type + Age + Largest.lesion + ALC.preLD + LDH.preLD, data = data1) %>%
  tbl_regression(exp = TRUE)
1 cases omitted due to missing values
Show code
tbl_merge(
  tbls = list(uv_tab, mv_tab),                          # combine
  tab_spanner = c("**Univariate**", "**Multivariable**")) # set header names
Characteristic Univariate Multivariable
HR1 95% CI1 p-value HR1 95% CI1 p-value
CAR.T.Product.Type





    Liso-cel

    Axi-cel 1.22 0.70, 2.13 0.5 1.10 0.61, 1.99 0.8
Age


1.00 0.98, 1.02 0.8
Largest.lesion


1.10 1.03, 1.18 0.007
ALC.preLD


1.31 1.20, 1.43 <0.001
LDH.preLD


1.00 1.00, 1.00 <0.001
1 HR = Hazard Ratio, CI = Confidence Interval

KAPLAN-MEIER ANALYSIS

Calculate length of follow-up

Show code
library(prodlim)
library(haven)

data1 = dataset %>%
  mutate(
    Reverse_death = ifelse(Death == 1, 0,1)
  )

#quantile(prodlim(Hist(time = Days.to.DLC/30, Death )~1, data = data1, reverse = TRUE ) )

reverse_km_OS <- survfit(Surv(Days.to.DLC/30, Reverse_death) ~ 1, data1)
reverse_km_OS
Call: survfit(formula = Surv(Days.to.DLC/30, Reverse_death) ~ 1, data = data1)

       n events median 0.95LCL 0.95UCL
[1,] 149     83   27.1    22.6    38.2
Show code
reverse_km_OS_breyanzi <- survfit(Surv(Days.to.DLC/30, Reverse_death) ~ 1, filter(data1, CAR.T.Product.Type == "Breyanzi") )
reverse_km_OS_breyanzi
Call: survfit(formula = Surv(Days.to.DLC/30, Reverse_death) ~ 1, data = filter(data1, 
    CAR.T.Product.Type == "Breyanzi"))

      n events median 0.95LCL 0.95UCL
[1,] 50     30   18.5    12.9    25.9
Show code
reverse_km_OS_yescarta <- survfit(Surv(Days.to.DLC/30, Reverse_death) ~ 1, filter(data1, CAR.T.Product.Type == "Yescarta") )
reverse_km_OS_yescarta
Call: survfit(formula = Surv(Days.to.DLC/30, Reverse_death) ~ 1, data = filter(data1, 
    CAR.T.Product.Type == "Yescarta"))

      n events median 0.95LCL 0.95UCL
[1,] 99     53     43    32.5    51.5

KM for OS, whole cohort

Show code
data1 = filter(dataset, Infused == 1)

km_OS <- survfit(Surv(Days.to.DLC/30, Death) ~ 1, data1)
km_OS
Call: survfit(formula = Surv(Days.to.DLC/30, Death) ~ 1, data = data1)

       n events median 0.95LCL 0.95UCL
[1,] 149     66   16.3    12.1    53.5
Show code
#autoplot(km_Regain)
OS_plot <- ggsurvplot(km_OS,
           pval=FALSE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           xlab="Time (months)", ylab = "Overall survival",
           xlim = c(0,36), break.x.by = c(180/30),
           ylim = c(0,1), break.y.by = c(0.25),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
) 

OS_plot

KM for OS, whole cohort

Show code
data1 = filter(dataset, Infused == 1)

km_PFS <- survfit(Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ 1, data1)
km_PFS
Call: survfit(formula = Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ 
    1, data = data1)

       n events median 0.95LCL 0.95UCL
[1,] 149     84   7.43    5.33    19.6
Show code
#autoplot(km_Regain)
PFS_plot <- ggsurvplot(km_PFS,
           pval=FALSE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           xlab="Time (months)", ylab = "Progression-free survival",
           xlim = c(0,36), break.x.by = c(180/30),
           ylim = c(0,1), break.y.by = c(0.25),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
) 

PFS_plot

Create KM for OS

Show code
data1 = filter(dataset, Infused == 1) %>%
  mutate(
    Reverse_death = ifelse(Death == 1, 0,1)
  )

km_OS <- survfit(Surv(Days.to.DLC/30, Death) ~ CAR.T.Product.Type, data1)
km_OS
Call: survfit(formula = Surv(Days.to.DLC/30, Death) ~ CAR.T.Product.Type, 
    data = data1)

                             n events median 0.95LCL 0.95UCL
CAR.T.Product.Type=Breyanzi 50     20   15.6    13.2      NA
CAR.T.Product.Type=Yescarta 99     46   16.0     9.4      NA
Show code
med_OS <- surv_median(km_OS)

p.logrank <- survdiff(Surv(Days.to.DLC/30, Death) ~ CAR.T.Product.Type, data1)$pvalue


oneYr <- summary(km_OS,times=c(12))
oneYr
Call: survfit(formula = Surv(Days.to.DLC/30, Death) ~ CAR.T.Product.Type, 
    data = data1)

                CAR.T.Product.Type=Breyanzi 
        time       n.risk      n.event     survival      std.err 
      12.000       21.000       14.000        0.655        0.077 
lower 95% CI upper 95% CI 
       0.520        0.825 

                CAR.T.Product.Type=Yescarta 
        time       n.risk      n.event     survival      std.err 
     12.0000      41.0000      35.0000       0.5543       0.0565 
lower 95% CI upper 95% CI 
      0.4540       0.6769 
Show code
oneYr$surv[1]- oneYr$surv[2] # Difference in survival at 1 yr for Breyanzi vs Yescarta
[1] 0.1008576
Show code
print("Difference in survival: ")
[1] "Difference in survival: "
Show code
diffSE <- sqrt(oneYr$std.err[2]^2 + oneYr$std.err[1]^2) # calculate the standard error

#Calculate the 95% CI for the difference
print("95% CI: ")
[1] "95% CI: "
Show code
oneYr$surv[1] - oneYr$surv[2] - 1.96 * diffSE
[1] -0.08635184
Show code
oneYr$surv[1] - oneYr$surv[2] + 1.96 * diffSE
[1] 0.288067
Show code
zStat <- (oneYr$surv[1] - oneYr$surv[2])/diffSE # calculate the c-test statistic

print("p-value: ")
[1] "p-value: "
Show code
p = 2 * pnorm(abs(zStat), lower.tail = FALSE) # calculate a two-sided p-value


#autoplot(km_Regain)
OS_plot <- ggsurvplot(km_OS,
           pval=FALSE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           xlab="Time (months)", ylab = "Overall survival",
           xlim = c(0,36), break.x.by = c(180/30),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("Liso-cel","Axi-cel"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
) 

OS_plot$plot <- OS_plot$plot + 
  geom_vline(xintercept = 12, linetype = "dashed", color = "steelblue") +
  geom_hline(yintercept = 0.5, linetype = "dashed", color = "black") +
  annotate("text", x = 12.5, y = 0.83, label = paste("Liso-cel vs axi-cel: 1-year OS\n", signif(oneYr$surv[1]*100, 2), "% vs ", signif(oneYr$surv[2]*100, 2), "%, p =", signif(p,2)), color = "steelblue", hjust = 0, vjust = -0.5, size = 3) +
  annotate("text", x = 13, y = 0, label = paste("Liso-cel vs axi-cel,\nmedian OS:\n", signif(med_OS$median[1], 2), "vs", signif(med_OS$median[2], 2), "months, p =", signif(p.logrank,2)), color = "black", hjust = 0, vjust = -0.5, size = 3, fontface = "bold")


OS_plot

Create KM for PFS, stratified by product

Show code
data1 <- filter(dataset, Infused == 1) #%>%
  #filter(Best.response == "CR" | Best.response == "PR") ## To view DOR instead of PFS

km_RFS <- survfit(Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ CAR.T.Product.Type, data = data1 )
km_RFS
Call: survfit(formula = Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ 
    CAR.T.Product.Type, data = data1)

                             n events median 0.95LCL 0.95UCL
CAR.T.Product.Type=Breyanzi 50     30   7.17    4.07    22.6
CAR.T.Product.Type=Yescarta 99     54   9.50    4.57    41.1
Show code
med_RFS <- surv_median(km_RFS)

p.logrank <- survdiff(Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ CAR.T.Product.Type, data1)$pvalue


oneYr <- summary(km_RFS,times=c(12))
oneYr
Call: survfit(formula = Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ 
    CAR.T.Product.Type, data = data1)

                CAR.T.Product.Type=Breyanzi 
        time       n.risk      n.event     survival      std.err 
     12.0000      12.0000      27.0000       0.3839       0.0776 
lower 95% CI upper 95% CI 
      0.2584       0.5705 

                CAR.T.Product.Type=Yescarta 
        time       n.risk      n.event     survival      std.err 
     12.0000      34.0000      46.0000       0.4591       0.0556 
lower 95% CI upper 95% CI 
      0.3621       0.5821 
Show code
oneYr$surv[1]- oneYr$surv[2] # Difference in survival at 1 yr for Breyanzi vs Yescarta
[1] -0.07517689
Show code
print("Difference in survival: ")
[1] "Difference in survival: "
Show code
diffSE <- sqrt(oneYr$std.err[2]^2 + oneYr$std.err[1]^2) # calculate the standard error

#Calculate the 95% CI for the difference
print("95% CI: ")
[1] "95% CI: "
Show code
oneYr$surv[1] - oneYr$surv[2] - 1.96 * diffSE
[1] -0.2622901
Show code
oneYr$surv[1] - oneYr$surv[2] + 1.96 * diffSE
[1] 0.1119363
Show code
zStat <- (oneYr$surv[1] - oneYr$surv[2])/diffSE # calculate the c-test statistic

print("p-value: ")
[1] "p-value: "
Show code
p = 2 * pnorm(abs(zStat), lower.tail = FALSE) # calculate a two-sided p-value


#autoplot(km_Regain)
RFS_plot <- ggsurvplot(km_RFS,
           pval=FALSE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           xlab="Time (months)", ylab = "Progression-free survival",
           xlim = c(0,36), break.x.by = c(180/30),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("Liso-cel","Axi-cel"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
) 

RFS_plot$plot <- RFS_plot$plot + 
  geom_vline(xintercept = 12, linetype = "dashed", color = "steelblue") +
  geom_hline(yintercept = 0.5, linetype = "dashed", color = "black") +
  annotate("text", x = 12.5, y = 0.83, label = paste("Liso-cel vs axi-cel: 1-year PFS\n", signif(oneYr$surv[1]*100, 2), "% vs ", signif(oneYr$surv[2]*100, 2), "%, p =", signif(p,2)), color = "steelblue", hjust = 0, vjust = -0.5, size = 3) +
  annotate("text", x = 13, y = .5, label = paste("Liso-cel vs axi-cel,\nmedian PFS:\n", signif(med_RFS$median[1], 2), "vs", signif(med_RFS$median[2], 2), "months, p =", signif(p.logrank,2)), color = "black", hjust = 0, vjust = -0.5, size = 3, fontface = "bold")


RFS_plot

Create KM for DOR, stratified by product

Show code
data1 <- filter(dataset, Infused == 1) %>%
  filter(Best.response == "CR" | Best.response == "PR") ## To view DOR instead of PFS

km_DOR <- survfit(Surv( (Days.to.relapse.death.or.DLC-Days.to.response)/30, Relapse.or.death) ~ CAR.T.Product.Type, data = data1 )
km_DOR
Call: survfit(formula = Surv((Days.to.relapse.death.or.DLC - Days.to.response)/30, 
    Relapse.or.death) ~ CAR.T.Product.Type, data = data1)

                             n events median 0.95LCL 0.95UCL
CAR.T.Product.Type=Breyanzi 40     20   11.0    5.83      NA
CAR.T.Product.Type=Yescarta 76     31   40.2    9.93      NA
Show code
med_DOR <- surv_median(km_DOR)

p.logrank <- survdiff(Surv( (Days.to.relapse.death.or.DLC-Days.to.response)/30, Relapse.or.death) ~ CAR.T.Product.Type, data1)$pvalue


oneYr <- summary(km_DOR,times=c(12))
oneYr
Call: survfit(formula = Surv((Days.to.relapse.death.or.DLC - Days.to.response)/30, 
    Relapse.or.death) ~ CAR.T.Product.Type, data = data1)

                CAR.T.Product.Type=Breyanzi 
        time       n.risk      n.event     survival      std.err 
     12.0000      12.0000      17.0000       0.4830       0.0906 
lower 95% CI upper 95% CI 
      0.3344       0.6977 

                CAR.T.Product.Type=Yescarta 
        time       n.risk      n.event     survival      std.err 
     12.0000      34.0000      23.0000       0.6054       0.0643 
lower 95% CI upper 95% CI 
      0.4916       0.7455 
Show code
oneYr$surv[1]- oneYr$surv[2] # Difference in survival at 1 yr for Breyanzi vs Yescarta
[1] -0.1223713
Show code
print("Difference in survival: ")
[1] "Difference in survival: "
Show code
diffSE <- sqrt(oneYr$std.err[2]^2 + oneYr$std.err[1]^2) # calculate the standard error

#Calculate the 95% CI for the difference
print("95% CI: ")
[1] "95% CI: "
Show code
oneYr$surv[1] - oneYr$surv[2] - 1.96 * diffSE
[1] -0.3401687
Show code
oneYr$surv[1] - oneYr$surv[2] + 1.96 * diffSE
[1] 0.09542613
Show code
zStat <- (oneYr$surv[1] - oneYr$surv[2])/diffSE # calculate the c-test statistic

print("p-value: ")
[1] "p-value: "
Show code
p = 2 * pnorm(abs(zStat), lower.tail = FALSE) # calculate a two-sided p-value


#autoplot(km_Regain)
DOR_plot <- ggsurvplot(km_DOR,
           pval=FALSE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           xlab="Time (months)", ylab = "Progression-free survival",
           xlim = c(0,36), break.x.by = c(180/30),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("Liso-cel","Axi-cel"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
) 

DOR_plot$plot <- DOR_plot$plot + 
  geom_vline(xintercept = 12, linetype = "dashed", color = "steelblue") +
  geom_hline(yintercept = 0.5, linetype = "dashed", color = "black") +
  annotate("text", x = 12.5, y = 0.83, label = paste("Liso-cel vs axi-cel: 1-year DOR\n", signif(oneYr$surv[1]*100, 2), "% vs ", signif(oneYr$surv[2]*100, 2), "%, p =", signif(p,2)), color = "steelblue", hjust = 0, vjust = -0.5, size = 3) +
  annotate("text", x = 13, y = .5, label = paste("Liso-cel vs axi-cel,\nmedian DOR:\n", signif(med_DOR$median[1], 2), "vs", signif(med_DOR$median[2], 2), "months, p =", signif(p.logrank,2)), color = "black", hjust = 0, vjust = -0.5, size = 3, fontface = "bold")


DOR_plot

Combined KM with OS and PFS

Show code
splots <- list()
splots[[1]] = OS_plot
splots[[2]] = RFS_plot
arrange_ggsurvplots(splots, print = TRUE,
  ncol = 2, nrow = 1, risk.table.height = 0.25)

Create KM for OS stratified by best response

Show code
km_OS <- survfit(Surv(Days.to.DLC/30, Death) ~ Best.response, data = filter(dataset, Infused == 1 & Best.response != "SD"))
km_OS
Call: survfit(formula = Surv(Days.to.DLC/30, Death) ~ Best.response, 
    data = filter(dataset, Infused == 1 & Best.response != "SD"))

                  n events median 0.95LCL 0.95UCL
Best.response=CR 77     21     NA   53.50      NA
Best.response=PD 32     25    5.5    3.67     9.7
Best.response=PR 39     19   13.5    6.77      NA
Show code
#autoplot(km_Regain)

OS_plot <- ggsurvplot(km_OS,
           pval=TRUE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.3,
           tables.theme = theme_cleantable(),
           #surv.median.line = "hv", # Specify median survival
           #ggtheme = theme_bw(), # Change ggplot2 theme
           #palette = c("#E7B800", "#2E9FDF"),
           xlab="Time (months)", ylab = "Overall survival",
           xlim = c(0,72), break.x.by = c(12),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("CR","PD", "PR"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
)
OS_plot

Create KM for OS stratified by Bulky disease (>=5cm) status

Show code
km_OS <- survfit(Surv(Days.to.DLC/30, Death) ~ Bulky, data = filter(dataset, Infused == 1 | Best.response != "") )
km_OS
Call: survfit(formula = Surv(Days.to.DLC/30, Death) ~ Bulky, data = filter(dataset, 
    Infused == 1 | Best.response != ""))

          n events median 0.95LCL 0.95UCL
Bulky=0 105     39  43.23    16.0      NA
Bulky=1  44     27   6.37     4.7    13.5
Show code
#autoplot(km_Regain)
OS_plot <- ggsurvplot(km_OS,
           pval=TRUE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           xlab="Time (months)", ylab = "Overall survival",
           xlim = c(0,72), break.x.by = c(12),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("Non-bulky","Bulky"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
)
OS_plot

Create KM for OS stratified by Breyanzi out-of-spec (EAP) status

Show code
km_OS <- survfit(Surv(Days.to.DLC, Death) ~ EAP, data = filter(dataset, CAR.T.Product.Type == "Breyanzi") )
km_OS
Call: survfit(formula = Surv(Days.to.DLC, Death) ~ EAP, data = filter(dataset, 
    CAR.T.Product.Type == "Breyanzi"))

       n events median 0.95LCL 0.95UCL
EAP=0 39     16    409     357      NA
EAP=1 11      4     NA     252      NA
Show code
OS_plot <- ggsurvplot(km_OS,
           pval=TRUE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           xlab="Time (days)", ylab = "Overall survival",
           xlim = c(0,1080), break.x.by = c(180),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("In-spec", "Out-of-spec"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
)
OS_plot

Create KM for OS stratified by LDH status (<210 vs >=210 U/L)

Show code
data1 = filter(dataset, Infused == 1)

km_OS <- survfit(Surv(Days.to.DLC/30, Death) ~ High.LDH, data1)
km_OS
Call: survfit(formula = Surv(Days.to.DLC/30, Death) ~ High.LDH, data = data1)

   1 observation deleted due to missingness 
            n events median 0.95LCL 0.95UCL
High.LDH=0 84     29  43.23   24.30      NA
High.LDH=1 64     36   6.77    4.57    11.9
Show code
#autoplot(km_Regain)


OS_plot <- ggsurvplot(km_OS,
           pval=TRUE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           #surv.median.line = "hv", # Specify median survival
           #ggtheme = theme_bw(), # Change ggplot2 theme
           #palette = c("#E7B800", "#2E9FDF"),
           xlab="Time (months)", ylab = "Overall survival",
           xlim = c(0,72), break.x.by = c(12),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("LDH <210 U/L", "LDH \u2265210 U/L"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
)
OS_plot

Create KM for OS stratified by HCT-CI status (>=3 vs <3)

Show code
data1 = filter(dataset, Infused == 1) %>%
  mutate(
    High.HCT.CI = ifelse(HCT.CI >=3,1,0) )

km_OS <- survfit(Surv(Days.to.DLC/30, Death) ~ High.HCT.CI, data1 )
km_OS
Call: survfit(formula = Surv(Days.to.DLC/30, Death) ~ High.HCT.CI, 
    data = data1)

                n events median 0.95LCL 0.95UCL
High.HCT.CI=0 100     42   16.3   13.07      NA
High.HCT.CI=1  49     24   16.0    8.97      NA
Show code
OS_plot <- ggsurvplot(km_OS,
           pval=TRUE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           #surv.median.line = "hv", # Specify median survival
           #ggtheme = theme_bw(), # Change ggplot2 theme
           #palette = c("#E7B800", "#2E9FDF"),
           xlab="Time (months)", ylab = "Overall survival",
           xlim = c(0,72), break.x.by = c(12),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("HCT <3", "HCT \u22653"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
)
OS_plot

Create KM for OS stratified by bridging response category

Show code
data1 = dataset %>%
  mutate(
    Bridging.response.category = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
    )

km_OS <- survfit(Surv(Days.to.DLC/30, Death) ~ Bridging.response.category, data1 )
km_OS
Call: survfit(formula = Surv(Days.to.DLC/30, Death) ~ Bridging.response.category, 
    data = data1)

   4 observations deleted due to missingness 
                                        n events median 0.95LCL
Bridging.response.category=No bridging 88     32  43.97   16.00
Bridging.response.category=CR/PR       21      9  13.57    7.07
Bridging.response.category=SD/PD       36     23   6.53    4.70
                                       0.95UCL
Bridging.response.category=No bridging      NA
Bridging.response.category=CR/PR            NA
Bridging.response.category=SD/PD          13.6
Show code
OS_plot <- ggsurvplot(km_OS,
           pval=TRUE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           #surv.median.line = "hv", # Specify median survival
           #ggtheme = theme_bw(), # Change ggplot2 theme
           #palette = c("#E7B800", "#2E9FDF"),
           xlab="Time (months)", ylab = "Overall survival",
           xlim = c(0,72), break.x.by = c(12),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("No bridging","CR/PR","SD/PD"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
)
OS_plot

Create KM for PFS stratified by best response

Show code
km_PFS <- survfit(Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ Best.response, data = filter(dataset, Infused == 1 & Best.response != "SD"& Best.response != "PD") )
km_PFS
Call: survfit(formula = Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ 
    Best.response, data = filter(dataset, Infused == 1 & Best.response != 
    "SD" & Best.response != "PD"))

                  n events median 0.95LCL 0.95UCL
Best.response=CR 77     27     NA   22.57      NA
Best.response=PR 39     24   4.07    3.47    19.6
Show code
#autoplot(km_Regain)

PFS_plot <- ggsurvplot(km_PFS,
           pval=TRUE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           #surv.median.line = "hv", # Specify median survival
           #ggtheme = theme_bw(), # Change ggplot2 theme
           #palette = c("#E7B800", "#2E9FDF"),
           xlab="Time (months)", ylab = "Progression-free survival",
           xlim = c(0,72), break.x.by = c(12),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("CR", "PR"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
)
PFS_plot

Create KM for PFS stratified by Bulky disease (>=5cm) status

Show code
km_PFS <- survfit(Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ Bulky, data = filter(dataset, Infused == 1 | Best.response != "") )
km_PFS
Call: survfit(formula = Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ 
    Bulky, data = filter(dataset, Infused == 1 | Best.response != 
    ""))

          n events median 0.95LCL 0.95UCL
Bulky=0 105     55  11.90    6.77      44
Bulky=1  44     29   3.63    1.47      22
Show code
#autoplot(km_Regain)
PFS_plot <- ggsurvplot(km_PFS,
           pval=TRUE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           xlab="Time (months)", ylab = "Progression-free survival",
           xlim = c(0,72), break.x.by = c(12),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("Non-bulky","Bulky"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
)
PFS_plot

Create KM for PFS stratified by Breyanzi out-of-spec (EAP) status

Show code
km_PFS <- survfit(Surv(Days.to.DLC/30, Relapse.or.death) ~ EAP, data = filter(dataset, CAR.T.Product.Type == "Breyanzi") )
km_PFS
Call: survfit(formula = Surv(Days.to.DLC/30, Relapse.or.death) ~ EAP, 
    data = filter(dataset, CAR.T.Product.Type == "Breyanzi"))

       n events median 0.95LCL 0.95UCL
EAP=0 39     22   13.2    8.67    25.5
EAP=1 11      8   24.5    8.40      NA
Show code
PFS_plot <- ggsurvplot(km_PFS,
           pval=TRUE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           xlab="Time (months)", ylab = "Progression-free survival",
           xlim = c(0,72), break.x.by = c(12),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("In-spec", "Out-of-spec"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
)
PFS_plot

Create KM for PFS stratified by LDH status (<210 vs >=210 U/L)

Show code
data1 = filter(dataset, Infused == 1)

km_PFS <- survfit(Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ High.LDH, data1)
km_PFS
Call: survfit(formula = Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ 
    High.LDH, data = data1)

   1 observation deleted due to missingness 
            n events median 0.95LCL 0.95UCL
High.LDH=0 84     44  19.17    7.20    47.5
High.LDH=1 64     39   3.63    2.83    10.9
Show code
#autoplot(km_Regain)


PFS_plot <- ggsurvplot(km_PFS,
           pval=TRUE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           #surv.median.line = "hv", # Specify median survival
           #ggtheme = theme_bw(), # Change ggplot2 theme
           #palette = c("#E7B800", "#2E9FDF"),
           xlab="Time (months)", ylab = "Progression-free survival",
           xlim = c(0,72), break.x.by = c(12),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("LDH <210 U/L", "LDH \u2265210 U/L"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
)
PFS_plot

Create KM for PFS stratified by HCT-CI status (>=3 vs <3)

Show code
data1 = filter(dataset, Infused == 1) %>%
  mutate(
    High.HCT.CI = ifelse(HCT.CI >=3,1,0) )

km_PFS <- survfit(Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ High.HCT.CI, data1 )
km_PFS
Call: survfit(formula = Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ 
    High.HCT.CI, data = data1)

                n events median 0.95LCL 0.95UCL
High.HCT.CI=0 100     53   7.43    4.67    24.3
High.HCT.CI=1  49     31   6.07    3.27    41.1
Show code
PFS_plot <- ggsurvplot(km_PFS,
           pval=TRUE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           #surv.median.line = "hv", # Specify median survival
           #ggtheme = theme_bw(), # Change ggplot2 theme
           #palette = c("#E7B800", "#2E9FDF"),
           xlab="Time (months)", ylab = "Progression-free survival",
           xlim = c(0,72), break.x.by = c(12),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("HCT <3", "HCT \u22653"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
)
PFS_plot

Create KM for PFS stratified by bridging response category

Show code
data1 = dataset %>%
  mutate(
    Bridging.response.category = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
    )

km_PFS <- survfit(Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ Bridging.response.category, data1 )
km_PFS
Call: survfit(formula = Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ 
    Bridging.response.category, data = data1)

   4 observations deleted due to missingness 
                                        n events median 0.95LCL
Bridging.response.category=No bridging 88     40  39.77   10.33
Bridging.response.category=CR/PR       21     12   7.43    3.67
Bridging.response.category=SD/PD       36     28   3.23    2.23
                                       0.95UCL
Bridging.response.category=No bridging      NA
Bridging.response.category=CR/PR            NA
Bridging.response.category=SD/PD          7.17
Show code
PFS_plot <- ggsurvplot(km_PFS,
           pval=TRUE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.3,
           tables.theme = theme_cleantable(),
           #surv.median.line = "hv", # Specify median survival
           #ggtheme = theme_bw(), # Change ggplot2 theme
           #palette = c("#E7B800", "#2E9FDF"),
           xlab="Time (months)", ylab = "Progression-free survival",
           xlim = c(0,72), break.x.by = c(12),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("No bridging","CR/PR","SD/PD"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
)
PFS_plot

WEIGHTED KM PLOTS

Create weighted KM for OS

Show code
data1 = IPTW.data

km_OS <- survfit(Surv(Days.to.DLC/30, Death) ~ CAR.T.Product.Type, data1, weights=weights)
km_OS
Call: survfit(formula = Surv(Days.to.DLC/30, Death) ~ CAR.T.Product.Type, 
    data = data1, weights = weights)

                            records    n events median 0.95LCL
CAR.T.Product.Type=Breyanzi      50 40.6   17.3   15.6   11.90
CAR.T.Product.Type=Yescarta      99 86.1   40.3   16.3    8.97
                            0.95UCL
CAR.T.Product.Type=Breyanzi      NA
CAR.T.Product.Type=Yescarta      NA
Show code
med_OS <- surv_median(km_OS)

p.logrank <- survdiff(Surv(Days.to.DLC/30, Death) ~ CAR.T.Product.Type, data1)$pvalue


oneYr <- summary(km_OS,times=c(12))
oneYr
Call: survfit(formula = Surv(Days.to.DLC/30, Death) ~ CAR.T.Product.Type, 
    data = data1, weights = weights)

                CAR.T.Product.Type=Breyanzi 
        time       n.risk      n.event     survival      std.err 
     12.0000      16.0336      13.7107       0.6008       0.0883 
lower 95% CI upper 95% CI 
      0.4504       0.8013 

                CAR.T.Product.Type=Yescarta 
        time       n.risk      n.event     survival      std.err 
      12.000       36.110       30.479        0.555        0.061 
lower 95% CI upper 95% CI 
       0.447        0.689 
Show code
oneYr$surv[1]- oneYr$surv[2] # Difference in survival at 1 yr for Breyanzi vs Yescarta
[1] 0.04569224
Show code
print("Difference in survival: ")
[1] "Difference in survival: "
Show code
diffSE <- sqrt(oneYr$std.err[2]^2 + oneYr$std.err[1]^2) # calculate the standard error

#Calculate the 95% CI for the difference
print("95% CI: ")
[1] "95% CI: "
Show code
oneYr$surv[1] - oneYr$surv[2] - 1.96 * diffSE
[1] -0.1646864
Show code
oneYr$surv[1] - oneYr$surv[2] + 1.96 * diffSE
[1] 0.2560708
Show code
zStat <- (oneYr$surv[1] - oneYr$surv[2])/diffSE # calculate the c-test statistic

print("p-value: ")
[1] "p-value: "
Show code
p = 2 * pnorm(abs(zStat), lower.tail = FALSE) # calculate a two-sided p-value


#autoplot(km_Regain)
OS_plot <- ggsurvplot(km_OS,
           pval=FALSE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           xlab="Time (months)", ylab = "Overall survival",
           xlim = c(0,36), break.x.by = c(180/30),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("Liso-cel","Axi-cel"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
) 

OS_plot$plot <- OS_plot$plot + 
  geom_vline(xintercept = 12, linetype = "dashed", color = "steelblue") +
  geom_hline(yintercept = 0.5, linetype = "dashed", color = "black") +
  annotate("text", x = 12.5, y = 0.83, label = paste("Liso-cel vs axi-cel: 1-year OS\n", signif(oneYr$surv[1]*100, 2), "% vs ", signif(oneYr$surv[2]*100, 2), "%, p =", signif(p,2)), color = "steelblue", hjust = 0, vjust = -0.5, size = 3) +
  annotate("text", x = 13, y = 0, label = paste("Liso-cel vs axi-cel,\nmedian OS:\n", signif(med_OS$median[1], 2), "vs", signif(med_OS$median[2], 2), "months, p =", signif(p.logrank,2)), color = "black", hjust = 0, vjust = -0.5, size = 3, fontface = "bold")


OS_plot

Create weighted KM for PFS, stratified by product

Show code
data1 = IPTW.data

km_RFS <- survfit(Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ CAR.T.Product.Type, data = data1, weights=weights )
km_RFS
Call: survfit(formula = Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ 
    CAR.T.Product.Type, data = data1, weights = weights)

                            records    n events median 0.95LCL
CAR.T.Product.Type=Breyanzi      50 40.6   23.1   7.43    4.67
CAR.T.Product.Type=Yescarta      99 86.1   46.6  10.33    4.90
                            0.95UCL
CAR.T.Product.Type=Breyanzi      NA
CAR.T.Product.Type=Yescarta    47.5
Show code
med_RFS <- surv_median(km_RFS)

p.logrank <- survdiff(Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ CAR.T.Product.Type, data1)$pvalue


oneYr <- summary(km_RFS,times=c(12))
oneYr
Call: survfit(formula = Surv(Days.to.relapse.death.or.DLC/30, Relapse.or.death) ~ 
    CAR.T.Product.Type, data = data1, weights = weights)

                CAR.T.Product.Type=Breyanzi 
        time       n.risk      n.event     survival      std.err 
     12.0000       9.6155      20.9003       0.3951       0.0873 
lower 95% CI upper 95% CI 
      0.2562       0.6092 

                CAR.T.Product.Type=Yescarta 
        time       n.risk      n.event     survival      std.err 
     12.0000      30.4878      39.6663       0.4697       0.0597 
lower 95% CI upper 95% CI 
      0.3662       0.6025 
Show code
oneYr$surv[1]- oneYr$surv[2] # Difference in survival at 1 yr for Breyanzi vs Yescarta
[1] -0.07463201
Show code
print("Difference in survival: ")
[1] "Difference in survival: "
Show code
diffSE <- sqrt(oneYr$std.err[2]^2 + oneYr$std.err[1]^2) # calculate the standard error

#Calculate the 95% CI for the difference
print("95% CI: ")
[1] "95% CI: "
Show code
oneYr$surv[1] - oneYr$surv[2] - 1.96 * diffSE
[1] -0.281858
Show code
oneYr$surv[1] - oneYr$surv[2] + 1.96 * diffSE
[1] 0.132594
Show code
zStat <- (oneYr$surv[1] - oneYr$surv[2])/diffSE # calculate the c-test statistic

print("p-value: ")
[1] "p-value: "
Show code
p = 2 * pnorm(abs(zStat), lower.tail = FALSE) # calculate a two-sided p-value


#autoplot(km_Regain)
RFS_plot <- ggsurvplot(km_RFS,
           pval=FALSE,
           conf.int = TRUE,
           risk.table = TRUE, # Add risk table
           fontsize = 6,
           risk.table.col = "strata", # Change risk table color by groups
           tables.height = 0.25,
           tables.theme = theme_cleantable(),
           xlab="Time (months)", ylab = "Progression-free survival",
           xlim = c(0,36), break.x.by = c(180/30),
           ylim = c(0,1), break.y.by = c(0.25),
           legend.labs = c("Liso-cel","Axi-cel"),
           legend = "none",
           surv.scale="percent",
           font.main = c(16, "plain", "black"),
           font.x = c(16, "plain", "black"),
           font.y = c(16, "plain", "black"),
           font.caption = c(16, "plain", "black"),
           font.tickslab = c(16, "plain", "black")
) 

RFS_plot$plot <- RFS_plot$plot + 
  geom_vline(xintercept = 12, linetype = "dashed", color = "steelblue") +
  geom_hline(yintercept = 0.5, linetype = "dashed", color = "black") +
  annotate("text", x = 12.5, y = 0.83, label = paste("Liso-cel vs axi-cel: 1-year PFS\n", signif(oneYr$surv[1]*100, 2), "% vs ", signif(oneYr$surv[2]*100, 2), "%, p =", signif(p,2)), color = "steelblue", hjust = 0, vjust = -0.5, size = 3) +
  annotate("text", x = 13, y = .55, label = paste("Liso-cel vs axi-cel,\nmedian PFS:\n", signif(med_RFS$median[1], 2), "vs", signif(med_RFS$median[2], 2), "months, p =", signif(p.logrank,2)), color = "black", hjust = 0, vjust = -0.5, size = 3, fontface = "bold")


RFS_plot

REGRESSION ANALYSIS: UNWEIGHTED AND IPTW

PFS/OS

Cox Model - PFS

Show code
theme_gtsummary_compact()
preds <- c("Product", "LDH pre-LD", "ALC pre-LD","Largest lesion", "Age", "Male sex", "Bridging category")

data0 <- dataset %>%
  mutate(
    "Male sex" = ifelse(Sex == "M",1,0),
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Largest lesion" = Largest.lesion,
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data1 <- IPTW.data %>%
  mutate(
    "Male sex" = ifelse(Sex == "M",1,0),
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Largest lesion" = Largest.lesion,
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD")),
  )

data2 <- m.data %>%
  mutate(
    "Male sex" = ifelse(Sex == "M",1,0),
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Largest lesion" = Largest.lesion,
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD")),
  )

uv_tab <- tbl_uvregression(
  data0[c(preds)],
  method = coxph,
  y = Surv(data0$Days.to.relapse.death.or.DLC, data0$Relapse.or.death),
  exponentiate = TRUE
)

mv_tab<-coxph( Surv(Days.to.relapse.death.or.DLC, Relapse.or.death) ~ Product + `LDH pre-LD`+  `ALC pre-LD` + `Largest lesion` + Age+ `Male sex` + `Bridging category`, data0) %>% tbl_regression(exponentiate=TRUE)


uv_tab_IPTW <- tbl_uvregression(
  data1[c(preds)],
  method = coxph,
  y = Surv(data1$Days.to.relapse.death.or.DLC, data1$Relapse.or.death),
  exponentiate = TRUE,
  method.args = list(weights = data1$weights),
)

mv_tab_IPTW<-coxph( Surv(Days.to.relapse.death.or.DLC, Relapse.or.death) ~ Product + `LDH pre-LD`+  `ALC pre-LD` + `Largest lesion` + Age + `Male sex` + `Bridging category`, data1, weights=weights) %>%tbl_regression( exponentiate=TRUE)

uv_tab_PSM <- tbl_uvregression(
  data2[c(preds)],
  method = coxph,
  y = Surv(data2$Days.to.relapse.death.or.DLC, data2$Relapse.or.death),
  exponentiate = TRUE,
  method.args = list(weights = data2$weights),
)

mv_tab_PSM<-coxph( Surv(Days.to.relapse.death.or.DLC, Relapse.or.death) ~ Product + `LDH pre-LD`+  `ALC pre-LD` + `Largest lesion` + Age + `Male sex` + `Bridging category`, data2, weights=weights) %>%tbl_regression( exponentiate=TRUE)


row1 <- tbl_merge(list(uv_tab, mv_tab), tab_spanner = c("**Univariate**", "**Multivariable**"))
row2 <- tbl_merge(list(uv_tab_IPTW, mv_tab_IPTW))
row3 <- tbl_merge(list(uv_tab_PSM, mv_tab_PSM))
tbl_stack(list(row1, row2, row3), group_header = c("UNWEIGHTED ANALYSIS", "IPTW ANALYSIS", "PSM ANALYSIS"), quiet=TRUE)
Characteristic Univariate Multivariable
N HR1 95% CI1 p-value HR1 95% CI1 p-value
UNWEIGHTED ANALYSIS
Product 149





    Liso-cel


    Axi-cel
0.85 0.54, 1.34 0.5 0.93 0.56, 1.54 0.8
LDH pre-LD 148 1.14 1.01, 1.28 0.037 1.10 0.96, 1.26 0.2
ALC pre-LD 149 1.11 0.96, 1.29 0.2 1.11 0.99, 1.25 0.069
Largest lesion 149 1.08 1.02, 1.14 0.011 1.05 0.98, 1.12 0.2
Age 149 1.0 0.98, 1.01 0.5 1.00 0.98, 1.02 0.7
Male sex 149 1.05 0.67, 1.64 0.8 1.28 0.78, 2.09 0.3
Bridging category 145





    No bridging


    CR/PR
1.58 0.83, 3.04 0.2 1.69 0.86, 3.32 0.13
    SD/PD
2.68 1.63, 4.39 <0.001 2.31 1.29, 4.13 0.005
IPTW ANALYSIS
Product 126





    Liso-cel


    Axi-cel
0.90 0.56, 1.46 0.7 1.07 0.64, 1.79 0.8
LDH pre-LD 125 1.14 1.08, 1.21 <0.001 1.11 1.04, 1.18 0.001
ALC pre-LD 126 1.12 0.96, 1.31 0.15 1.13 1.05, 1.21 0.001
Largest lesion 126 1.05 0.99, 1.12 0.11 1.01 0.94, 1.09 0.7
Age 126 1.00 0.98, 1.02 0.8 1.00 0.98, 1.02 0.8
Male sex 126 1.03 0.63, 1.69 0.9 1.29 0.74, 2.25 0.4
Bridging category 123





    No bridging


    CR/PR
1.61 0.69, 3.74 0.3 1.71 0.67, 4.33 0.3
    SD/PD
2.62 1.60, 4.29 <0.001 2.60 1.44, 4.71 0.002
PSM ANALYSIS
Product 149





    Liso-cel


    Axi-cel
0.79 0.45, 1.39 0.4 0.87 0.50, 1.52 0.6
LDH pre-LD 148 1.23 1.09, 1.39 <0.001 1.19 1.06, 1.33 0.003
ALC pre-LD 149 1.16 1.07, 1.26 <0.001 1.15 1.09, 1.22 <0.001
Largest lesion 149 1.05 0.98, 1.13 0.2 0.99 0.92, 1.06 0.8
Age 149 0.99 0.97, 1.01 0.5 1.01 0.98, 1.03 0.6
Male sex 149 1.46 0.80, 2.67 0.2 1.71 0.99, 2.94 0.052
Bridging category 144





    No bridging


    CR/PR
1.04 0.32, 3.37 >0.9 1.02 0.31, 3.35 >0.9
    SD/PD
2.77 1.59, 4.81 <0.001 2.86 1.62, 5.07 <0.001
1 HR = Hazard Ratio, CI = Confidence Interval

Cox Model - PFS forest plots

Show code
## Forest plot for MV
df_fp <- mv_tab$table_body %>%
  select(header_row, label, N_obs, N_event, estimate, conf.low, conf.high, p.value, ) %>%
  mutate(
    label = ifelse(header_row == TRUE | is.na(header_row),as.character(label), paste0("     ", as.character(label)) ),
    p.value = signif(p.value, 2),
    `HR (95% CI)` = ifelse(
      is.na(estimate),"",paste0(round(estimate, 2), " (", round(conf.low,2), " to ",round(conf.high,2), ") ")
    )
  ) %>%
  rename(Characteristic = label,
         N = N_obs,
         Events = N_event,
         `p value` = p.value)
forester(
  left_side_data = df_fp[2],
  right_side_data = df_fp[9:8],
  estimate = df_fp$estimate,
  ci_low = df_fp$conf.low,
  ci_high = df_fp$conf.high,
  estimate_col_name = "HR (95% CI)",
  xlim = c(0.1, 10),
  null_line_at = 1,
  arrows = TRUE,
  x_scale_linear = FALSE,
  arrow_labels = c("Better", "Worse"),
  font_family = "sans",
  display = TRUE,
  nudge_x = .4,
  nudge_height = .06,
  stripe_colour = "#F5F5F5",
  file_path = "/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/PFS_mv_plot.png"
)

knitr::include_graphics("/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/PFS_mv_plot.png")
Show code
## Forest plot for MV IPTW
df_fp <- mv_tab_IPTW$table_body %>%
  select(header_row, label, N_obs, N_event, estimate, conf.low, conf.high, p.value, ) %>%
  mutate(
    label = ifelse(header_row == TRUE | is.na(header_row),as.character(label), paste0("     ", as.character(label)) ),
    p.value = signif(p.value, 2),
    `HR (95% CI)` = ifelse(
      is.na(estimate),"",paste0(round(estimate, 2), " (", round(conf.low,2), " to ",round(conf.high,2), ") ")
    )
  ) %>%
  rename(Characteristic = label,
         N = N_obs,
         Events = N_event,
         `p value` = p.value)
forester(
  left_side_data = df_fp[2],
  right_side_data = df_fp[9:8],
  estimate = df_fp$estimate,
  ci_low = df_fp$conf.low,
  ci_high = df_fp$conf.high,
  estimate_col_name = "HR (95% CI)",
  xlim = c(0.1, 10),
  null_line_at = 1,
  arrows = TRUE,
  x_scale_linear = FALSE,
  arrow_labels = c("Better", "Worse"),
  font_family = "sans",
  display = TRUE,
  nudge_x = .4,
  nudge_height = .06,
  stripe_colour = "#F5F5F5",
  file_path = "/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/PFS_mv_plot_IPTW.png"
)

knitr::include_graphics("/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/PFS_mv_plot_IPTW.png")
Show code
## Forest plot for MV PSM
df_fp <- mv_tab_PSM$table_body %>%
  select(header_row, label, N_obs, N_event, estimate, conf.low, conf.high, p.value, ) %>%
  mutate(
    label = ifelse(header_row == TRUE | is.na(header_row),as.character(label), paste0("     ", as.character(label)) ),
    p.value = signif(p.value, 2),
    `HR (95% CI)` = ifelse(
      is.na(estimate),"",paste0(round(estimate, 2), " (", round(conf.low,2), " to ",round(conf.high,2), ") ")
    )
  ) %>%
  rename(Characteristic = label,
         N = N_obs,
         Events = N_event,
         `p value` = p.value)
forester(
  left_side_data = df_fp[2],
  right_side_data = df_fp[9:8],
  estimate = df_fp$estimate,
  ci_low = df_fp$conf.low,
  ci_high = df_fp$conf.high,
  estimate_col_name = "HR (95% CI)",
  xlim = c(0.1, 10),
  null_line_at = 1,
  arrows = TRUE,
  x_scale_linear = FALSE,
  arrow_labels = c("Better", "Worse"),
  font_family = "sans",
  display = TRUE,
  nudge_x = .4,
  nudge_height = .06,
  stripe_colour = "#F5F5F5",
  file_path = "/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/PFS_mv_plot_PSM.png"
)

knitr::include_graphics("/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/PFS_mv_plot_PSM.png")

Cox Model - OS

Show code
theme_gtsummary_compact()
preds <- c("Product","LDH pre-LD", "ALC pre-LD","Largest lesion", "Age", "Male sex", "Bridging category")

data0 <- dataset %>%
  mutate(
    "Male sex" = ifelse(Sex == "M",1,0),
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Largest lesion" = Largest.lesion,
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data1 <- IPTW.data %>%
  mutate(
    "Male sex" = ifelse(Sex == "M",1,0),
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Largest lesion" = Largest.lesion,
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data2 <- m.data %>%
  mutate(
    "Male sex" = ifelse(Sex == "M",1,0),
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Largest lesion" = Largest.lesion,
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

uv_tab <- tbl_uvregression(
  data0[c(preds)],
  method = coxph,
  y = Surv(data0$Days.to.DLC, data0$Death),
  exponentiate = TRUE
)

mv_tab<-coxph( Surv(Days.to.DLC, Death) ~ Product +`LDH pre-LD` +  `ALC pre-LD` +  `Largest lesion` + Age + `Male sex` + `Bridging category`, data0) %>% tbl_regression(exponentiate=TRUE)


uv_tab_IPTW <- tbl_uvregression(
  data1[c(preds)],
  method = coxph,
  y = Surv(data1$Days.to.DLC, data1$Death),
  exponentiate = TRUE,
  method.args = list(weights = data1$weights),
)

mv_tab_IPTW<-coxph( Surv(Days.to.DLC, Death) ~ Product +`LDH pre-LD` +  `ALC pre-LD` +  `Largest lesion` + Age + `Male sex` + `Bridging category`, data1, weights=weights) %>% tbl_regression(exponentiate=TRUE)

uv_tab_PSM <- tbl_uvregression(
  data2[c(preds)],
  method = coxph,
  y = Surv(data2$Days.to.DLC, data2$Death),
  exponentiate = TRUE,
  method.args = list(weights = data2$weights),
)

mv_tab_PSM<-coxph( Surv(Days.to.DLC, Death) ~ Product +`LDH pre-LD` +  `ALC pre-LD` +  `Largest lesion` + Age + `Male sex` + `Bridging category`, data2, weights=weights) %>% tbl_regression(exponentiate=TRUE)



row1 <- tbl_merge(list(uv_tab, mv_tab), tab_spanner = c("**Univariate**", "**Multivariable**"))
row2 <- tbl_merge(list(uv_tab_IPTW, mv_tab_IPTW))
row3 <- tbl_merge(list(uv_tab_PSM, mv_tab_PSM))
tbl_stack(list(row1, row2, row3), group_header = c("UNWEIGHTED ANALYSIS", "IPTW ANALYSIS", "PSM ANALYSIS"), quiet=TRUE)
Characteristic Univariate Multivariable
N HR1 95% CI1 p-value HR1 95% CI1 p-value
UNWEIGHTED ANALYSIS
Product 149





    Liso-cel


    Axi-cel
1.19 0.69, 2.03 0.5 1.17 0.65, 2.13 0.6
LDH pre-LD 148 1.37 1.19, 1.58 <0.001 1.37 1.16, 1.61 <0.001
ALC pre-LD 149 1.23 1.04, 1.47 0.017 1.27 1.06, 1.52 0.010
Largest lesion 149 1.14 1.07, 1.21 <0.001 1.11 1.04, 1.19 0.002
Age 149 1.00 0.98, 1.02 0.7 1.00 0.98, 1.02 0.8
Male sex 149 1.12 0.66, 1.88 0.7 1.36 0.77, 2.39 0.3
Bridging category 145





    No bridging


    CR/PR
1.52 0.72, 3.21 0.3 1.85 0.85, 4.02 0.12
    SD/PD
2.77 1.60, 4.78 <0.001 2.07 1.09, 3.93 0.026
IPTW ANALYSIS
Product 126





    Liso-cel


    Axi-cel
1.10 0.62, 1.95 0.7 1.17 0.63, 2.17 0.6
LDH pre-LD 125 1.36 1.22, 1.51 <0.001 1.34 1.20, 1.50 <0.001
ALC pre-LD 126 1.24 1.07, 1.44 0.005 1.28 1.17, 1.41 <0.001
Largest lesion 126 1.13 1.07, 1.20 <0.001 1.10 1.03, 1.18 0.003
Age 126 1.00 0.98, 1.02 0.8 1.00 0.97, 1.02 0.8
Male sex 126 1.06 0.60, 1.85 0.8 1.38 0.73, 2.61 0.3
Bridging category 123





    No bridging


    CR/PR
1.51 0.64, 3.53 0.3 1.74 0.68, 4.45 0.3
    SD/PD
2.96 1.66, 5.27 <0.001 2.35 1.21, 4.59 0.012
PSM ANALYSIS
Product 149





    Liso-cel


    Axi-cel
1.06 0.56, 1.98 0.9 1.14 0.59, 2.21 0.7
LDH pre-LD 148 1.49 1.30, 1.72 <0.001 1.45 1.24, 1.71 <0.001
ALC pre-LD 149 1.33 1.21, 1.45 <0.001 1.38 1.12, 1.70 0.003
Largest lesion 149 1.14 1.07, 1.22 <0.001 1.09 1.01, 1.17 0.028
Age 149 1.00 0.96, 1.03 0.9 1.00 0.97, 1.05 0.8
Male sex 149 1.32 0.68, 2.59 0.4 1.26 0.66, 2.40 0.5
Bridging category 144





    No bridging


    CR/PR
1.29 0.40, 4.12 0.7 1.41 0.42, 4.72 0.6
    SD/PD
3.15 1.56, 6.33 0.001 2.68 1.31, 5.48 0.007
1 HR = Hazard Ratio, CI = Confidence Interval

Cox Model - OS forest plots

Show code
## Forest plot for MV
df_fp <- mv_tab$table_body %>%
  select(header_row, label, N_obs, N_event, estimate, conf.low, conf.high, p.value, ) %>%
  mutate(
    label = ifelse(header_row == TRUE | is.na(header_row),as.character(label), paste0("     ", as.character(label)) ),
    p.value = signif(p.value, 2),
    `HR (95% CI)` = ifelse(
      is.na(estimate),"",paste0(round(estimate, 2), " (", round(conf.low,2), " to ",round(conf.high,2), ") ")
    )
  ) %>%
  rename(Characteristic = label,
         N = N_obs,
         Events = N_event,
         `p value` = p.value)
forester(
  left_side_data = df_fp[2],
  right_side_data = df_fp[9:8],
  estimate = df_fp$estimate,
  ci_low = df_fp$conf.low,
  ci_high = df_fp$conf.high,
  estimate_col_name = "HR (95% CI)",
  xlim = c(0.1, 10),
  null_line_at = 1,
  arrows = TRUE,
  x_scale_linear = FALSE,
  arrow_labels = c("Better", "Worse"),
  font_family = "sans",
  display = TRUE,
  nudge_x = .4,
  nudge_height = .06,
  stripe_colour = "#F5F5F5",
  file_path = "/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/OS_mv_plot.png"
)

knitr::include_graphics("/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/OS_mv_plot.png")
Show code
## Forest plot for MV IPTW
df_fp <- mv_tab_IPTW$table_body %>%
  select(header_row, label, N_obs, N_event, estimate, conf.low, conf.high, p.value, ) %>%
  mutate(
    label = ifelse(header_row == TRUE | is.na(header_row),as.character(label), paste0("     ", as.character(label)) ),
    p.value = signif(p.value, 2),
    `HR (95% CI)` = ifelse(
      is.na(estimate),"",paste0(round(estimate, 2), " (", round(conf.low,2), " to ",round(conf.high,2), ") ")
    )
  ) %>%
  rename(Characteristic = label,
         N = N_obs,
         Events = N_event,
         `p value` = p.value)
forester(
  left_side_data = df_fp[2],
  right_side_data = df_fp[9:8],
  estimate = df_fp$estimate,
  ci_low = df_fp$conf.low,
  ci_high = df_fp$conf.high,
  estimate_col_name = "HR (95% CI)",
  xlim = c(0.1, 10),
  null_line_at = 1,
  arrows = TRUE,
  x_scale_linear = FALSE,
  arrow_labels = c("Better", "Worse"),
  font_family = "sans",
  display = TRUE,
  nudge_x = .4,
  nudge_height = .06,
  stripe_colour = "#F5F5F5",
  file_path = "/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/OS_mv_plot_IPTW.png"
)

knitr::include_graphics("/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/OS_mv_plot_IPTW.png")
Show code
## Forest plot for MV PSM
df_fp <- mv_tab_PSM$table_body %>%
  select(header_row, label, N_obs, N_event, estimate, conf.low, conf.high, p.value, ) %>%
  mutate(
    label = ifelse(header_row == TRUE | is.na(header_row),as.character(label), paste0("     ", as.character(label)) ),
    p.value = signif(p.value, 2),
    `HR (95% CI)` = ifelse(
      is.na(estimate),"",paste0(round(estimate, 2), " (", round(conf.low,2), " to ",round(conf.high,2), ") ")
    )
  ) %>%
  rename(Characteristic = label,
         N = N_obs,
         Events = N_event,
         `p value` = p.value)
forester(
  left_side_data = df_fp[2],
  right_side_data = df_fp[9:8],
  estimate = df_fp$estimate,
  ci_low = df_fp$conf.low,
  ci_high = df_fp$conf.high,
  estimate_col_name = "HR (95% CI)",
  xlim = c(0.1, 10),
  null_line_at = 1,
  arrows = TRUE,
  x_scale_linear = FALSE,
  arrow_labels = c("Better", "Worse"),
  font_family = "sans",
  display = TRUE,
  nudge_x = .4,
  nudge_height = .06,
  stripe_colour = "#F5F5F5",
  file_path = "/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/OS_mv_plot_PSM.png"
)

knitr::include_graphics("/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/OS_mv_plot_PSM.png")

Cox diagnostics

PFS unweighted

Show code
data1 <- dataset %>%
  mutate(
    ferritin.max = log(ferritin.max),
    IL6.max = log(IL6.max),
    LDH.min = log(LDH.min),
    Age = Age,
    `Male sex` = ifelse(Sex == "M",1,0),
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    `ALC pre-LD` = ALC.preLD,
    `LDH pre-LD` = LDH.preLD/1000,
    `High LDH pre-LD` = ifelse(LDH.preLD >=210,1,0),
    `LDH day 0` = LDH.d0/1000,
    `ALC day 0` = ALC.d0,
    `Largest lesion` = Largest.lesion
  )

res.cox <-coxph( Surv(Days.to.relapse.death.or.DLC, Relapse.or.death) ~ Product + `LDH pre-LD` + `ALC pre-LD` + `Largest lesion` + Age + `Male sex`, data1)

## Testing proportional hazards assumption
test.ph <- cox.zph(res.cox)
test.ph
                  chisq df    p
Product           2.188  1 0.14
`LDH pre-LD`      2.538  1 0.11
`ALC pre-LD`      2.137  1 0.14
`Largest lesion`  1.293  1 0.26
Age               1.365  1 0.24
`Male sex`        0.215  1 0.64
GLOBAL           10.147  6 0.12

PFS IPTW

Show code
data1 <- IPTW.data %>%
  mutate(
    `Male sex` = ifelse(Sex == "M",1,0),
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    `ALC pre-LD` = ALC.preLD,
    `LDH pre-LD` = LDH.preLD/1000,
    `High LDH pre-LD` = ifelse(LDH.preLD >=210,1,0),
    `LDH day 0` = LDH.d0/1000,
    `ALC day 0` = ALC.d0,
    `Largest lesion` = Largest.lesion
  )

res.cox <-coxph( Surv(Days.to.relapse.death.or.DLC, Relapse.or.death) ~ Product + `LDH pre-LD` + `ALC pre-LD` + `Largest lesion`+ Age + `Male sex`, data1, weights=weights)

## Testing proportional hazards assumption
test.ph <- cox.zph(res.cox)
test.ph
                  chisq df     p
Product           3.459  1 0.063
`LDH pre-LD`      2.039  1 0.153
`ALC pre-LD`      1.558  1 0.212
`Largest lesion`  0.370  1 0.543
Age               2.558  1 0.110
`Male sex`        0.179  1 0.672
GLOBAL           10.079  6 0.121

PFS PSM

Show code
data1 <- m.data %>%
  mutate(
    `Male sex` = ifelse(Sex == "M",1,0),
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    `ALC pre-LD` = ALC.preLD,
    `LDH pre-LD` = LDH.preLD/1000,
    `High LDH pre-LD` = ifelse(LDH.preLD >=210,1,0),
    `LDH day 0` = LDH.d0/1000,
    `ALC day 0` = ALC.d0,
    `Largest lesion` = Largest.lesion
  )

res.cox <-coxph( Surv(Days.to.relapse.death.or.DLC, Relapse.or.death) ~ Product + `LDH pre-LD` + `ALC pre-LD` + `Largest lesion`+ Age + `Male sex`, data1, weights=weights)

## Testing proportional hazards assumption
test.ph <- cox.zph(res.cox)
test.ph
                 chisq df    p
Product          1.423  1 0.23
`LDH pre-LD`     0.991  1 0.32
`ALC pre-LD`     0.293  1 0.59
`Largest lesion` 0.338  1 0.56
Age              0.134  1 0.71
`Male sex`       1.066  1 0.30
GLOBAL           4.275  6 0.64

OS unweighted

Show code
data1 <- dataset %>%
  mutate(
    ferritin.max = log(ferritin.max),
    IL6.max = log(IL6.max),
    LDH.min = log(LDH.min),
    Age = Age,
    `Male sex` = ifelse(Sex == "M",1,0),
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    `ALC pre-LD` = ALC.preLD,
    `LDH pre-LD` = LDH.preLD/1000,
    `High LDH pre-LD` = ifelse(LDH.preLD >=210,1,0),
    `LDH day 0` = LDH.d0/1000,
    `ALC day 0` = ALC.d0,
    `Largest lesion` = Largest.lesion
  )

res.cox <-coxph( Surv(Days.to.DLC, Death) ~ Product + `LDH pre-LD` + `ALC pre-LD` + `Largest lesion`+ Age + `Male sex`, data1)

## Testing proportional hazards assumption
test.ph <- cox.zph(res.cox)
test.ph
                   chisq df     p
Product          5.85230  1 0.016
`LDH pre-LD`     0.00569  1 0.940
`ALC pre-LD`     1.17243  1 0.279
`Largest lesion` 2.27721  1 0.131
Age              1.69047  1 0.194
`Male sex`       0.01424  1 0.905
GLOBAL           9.93558  6 0.127

OS IPTW

Show code
data1 <- IPTW.data %>%
  mutate(
    ferritin.max = log(ferritin.max),
    IL6.max = log(IL6.max),
    LDH.min = log(LDH.min),
    Age = Age,
    `Male sex` = ifelse(Sex == "M",1,0),
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    `ALC pre-LD` = ALC.preLD,
    `LDH pre-LD` = LDH.preLD/1000,
    `High LDH pre-LD` = ifelse(LDH.preLD >=210,1,0),
    `LDH day 0` = LDH.d0/1000,
    `ALC day 0` = ALC.d0,
    `Largest lesion` = Largest.lesion
  )

res.cox <-coxph( Surv(Days.to.DLC, Death) ~ Product + `LDH pre-LD` + `ALC pre-LD` + `Largest lesion`+ Age + `Male sex`, data1, weights=weights)

## Testing proportional hazards assumption
test.ph <- cox.zph(res.cox)
test.ph
                  chisq df    p
Product          2.0630  1 0.15
`LDH pre-LD`     0.0402  1 0.84
`ALC pre-LD`     0.9209  1 0.34
`Largest lesion` 2.6437  1 0.10
Age              1.9744  1 0.16
`Male sex`       0.0519  1 0.82
GLOBAL           8.2084  6 0.22

OS PSM

Show code
data1 <- m.data %>%
  mutate(
    ferritin.max = log(ferritin.max),
    IL6.max = log(IL6.max),
    LDH.min = log(LDH.min),
    Age = Age,
    `Male sex` = ifelse(Sex == "M",1,0),
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    `ALC pre-LD` = ALC.preLD,
    `LDH pre-LD` = LDH.preLD/1000,
    `High LDH pre-LD` = ifelse(LDH.preLD >=210,1,0),
    `LDH day 0` = LDH.d0/1000,
    `ALC day 0` = ALC.d0,
    `Largest lesion` = Largest.lesion
  )

res.cox <-coxph( Surv(Days.to.DLC, Death) ~ Product + `LDH pre-LD` + `ALC pre-LD` + `Largest lesion`+ Age + `Male sex`, data1, weights=weights)

## Testing proportional hazards assumption
test.ph <- cox.zph(res.cox)
test.ph
                    chisq df     p
Product          2.54e+00  1 0.111
`LDH pre-LD`     5.45e-01  1 0.460
`ALC pre-LD`     2.65e-06  1 0.999
`Largest lesion` 1.24e+00  1 0.266
Age              5.66e+00  1 0.017
`Male sex`       2.56e-01  1 0.613
GLOBAL           1.14e+01  6 0.076

Response

Logistic Model - CR

Show code
theme_gtsummary_compact()
preds <- c("Best.CR", "Product", "LDH pre-LD","ALC pre-LD", "Largest lesion", "Age", "Male sex", "Bridging category") 

data0 <- dataset %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data1 <- IPTW.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data2 <- m.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

uv_tab <- tbl_uvregression(
  data0[c(preds)],
  method = glm,
  y = Best.CR,
  method.args = list(family = binomial),
  exponentiate = TRUE
)


mv_tab<-glm( Best.CR ~  `LDH pre-LD` + Product + `Largest lesion` + `ALC pre-LD` + `Age` + `Male sex` + `Bridging category`, data0, family = binomial ) %>%
  tbl_regression(exponentiate=TRUE)

uv_tab_IPTW <- tbl_uvregression(
  data1[c(preds)],
  method = glm,
  y = Best.CR,
  method.args = list(family = binomial, weights = data1$weights),
  exponentiate = TRUE
)

mv_tab_IPTW<-glm( Best.CR ~  `LDH pre-LD` +Product + `Largest lesion` + `ALC pre-LD` +  `Age` + `Male sex` + `Bridging category`, data1, weights=weights, family = binomial ) %>% 
  tbl_regression(exponentiate=TRUE)


uv_tab_PSM <- tbl_uvregression(
  data2[c(preds)],
  method = glm,
  y = Best.CR,
  method.args = list(family = binomial, weights = data2$weights),
  exponentiate = TRUE
)

mv_tab_PSM<-glm( Best.CR ~  `LDH pre-LD` +Product + `Largest lesion` + `ALC pre-LD` +  `Age` + `Male sex` + `Bridging category`, data2, weights=weights, family = binomial ) %>% 
  tbl_regression(exponentiate=TRUE)

row1 <- tbl_merge(list(uv_tab, mv_tab), tab_spanner = c("**Univariate**", "**Multivariable**"))
row2 <- tbl_merge(list(uv_tab_IPTW, mv_tab_IPTW))
row3 <- tbl_merge(list(uv_tab_PSM, mv_tab_PSM))
tbl_stack(list(row1, row2, row3), group_header = c("UNWEIGHTED ANALYSIS", "IPTW ANALYSIS", "PSM ANALYSIS"), quiet=TRUE)
Characteristic Univariate Multivariable
N OR1 95% CI1 p-value OR1 95% CI1 p-value
UNWEIGHTED ANALYSIS
Product 149





    Liso-cel


    Axi-cel
0.68 0.34, 1.35 0.3 0.61 0.26, 1.38 0.2
LDH pre-LD 148 0.14 0.02, 0.60 0.022 0.22 0.03, 0.89 0.083
ALC pre-LD 149 0.98 0.78, 1.19 0.8 1.02 0.73, 1.25 0.8
Largest lesion 149 0.86 0.77, 0.95 0.005 0.90 0.80, 1.00 0.064
Age 149 1.00 0.98, 1.03 >0.9 0.99 0.96, 1.02 0.5
Male sex 149 0.79 0.40, 1.53 0.5 0.73 0.34, 1.53 0.4
Bridging category 145





    No bridging


    CR/PR
0.92 0.35, 2.48 0.9 0.79 0.28, 2.25 0.6
    SD/PD
0.35 0.15, 0.77 0.011 0.51 0.20, 1.30 0.2
IPTW ANALYSIS
Product 126





    Liso-cel


    Axi-cel
0.65 0.30, 1.39 0.3 0.52 0.21, 1.21 0.14
LDH pre-LD 125 0.09 0.01, 0.52 0.022 0.12 0.01, 0.72 0.052
ALC pre-LD 126 0.96 0.71, 1.21 0.7 1.02 0.66, 1.30 0.9
Largest lesion 126 0.92 0.82, 1.01 0.091 0.96 0.86, 1.08 0.5
Age 126 1.00 0.97, 1.03 >0.9 0.99 0.96, 1.02 0.6
Male sex 126 0.99 0.47, 2.07 >0.9 0.85 0.37, 1.93 0.7
Bridging category 123





    No bridging


    CR/PR
0.69 0.25, 1.87 0.5 0.68 0.24, 1.98 0.5
    SD/PD
0.34 0.14, 0.82 0.017 0.42 0.15, 1.17 0.10
PSM ANALYSIS
Product 149





    Liso-cel


    Axi-cel
1.11 0.55, 2.20 0.8 1.02 0.45, 2.30 >0.9
LDH pre-LD 148 0.06 0.00, 0.44 0.016 0.07 0.00, 0.68 0.044
ALC pre-LD 149 0.96 0.75, 1.17 0.7 1.02 0.72, 1.27 0.9
Largest lesion 149 0.90 0.81, 1.00 0.060 0.98 0.86, 1.10 0.7
Age 149 1.03 1.00, 1.07 0.071 1.02 0.97, 1.06 0.5
Male sex 149 0.39 0.18, 0.78 0.009 0.37 0.16, 0.80 0.014
Bridging category 144





    No bridging


    CR/PR
0.91 0.36, 2.40 0.8 1.20 0.44, 3.52 0.7
    SD/PD
0.34 0.14, 0.81 0.015 0.70 0.24, 2.01 0.5
1 OR = Odds Ratio, CI = Confidence Interval

Logistic CR forest plots

Show code
## Forest plot for MV
df_fp <- mv_tab$table_body %>%
  select(header_row, label, N_obs, N_event, estimate, conf.low, conf.high, p.value, ) %>%
  mutate(
    label = ifelse(header_row == TRUE | is.na(header_row),as.character(label), paste0("     ", as.character(label)) ),
    p.value = signif(p.value, 2),
    `OR (95% CI)` = ifelse(
      is.na(estimate),"",paste0(round(estimate, 2), " (", round(conf.low,2), " to ",round(conf.high,2), ") ")
    )
  ) %>%
  rename(Characteristic = label,
         N = N_obs,
         Events = N_event,
         `p value` = p.value)
forester(
  left_side_data = df_fp[2],
  right_side_data = df_fp[9:8],
  estimate = df_fp$estimate,
  ci_low = df_fp$conf.low,
  ci_high = df_fp$conf.high,
  estimate_col_name = "OR (95% CI)",
  xlim = c(.05, 3),
  null_line_at = 1,
  arrows = TRUE,
  x_scale_linear = FALSE,
  arrow_labels = c("Worse", "Better"),
  font_family = "sans",
  display = TRUE,
  nudge_x = .4,
  nudge_height = .06,
  stripe_colour = "#F5F5F5",
  file_path = "/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/CR_mv_plot.png"
)

knitr::include_graphics("/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/CR_mv_plot.png")
Show code
## Forest plot for MV IPTW
df_fp <- mv_tab_IPTW$table_body %>%
  select(header_row, label, N_obs, N_event, estimate, conf.low, conf.high, p.value, ) %>%
  mutate(
    label = ifelse(header_row == TRUE | is.na(header_row),as.character(label), paste0("     ", as.character(label)) ),
    p.value = signif(p.value, 2),
    `OR (95% CI)` = ifelse(
      is.na(estimate),"",paste0(round(estimate, 2), " (", round(conf.low,2), " to ",round(conf.high,2), ") ")
    )
  ) %>%
  rename(Characteristic = label,
         N = N_obs,
         Events = N_event,
         `p value` = p.value)
forester(
  left_side_data = df_fp[2],
  right_side_data = df_fp[9:8],
  estimate = df_fp$estimate,
  ci_low = df_fp$conf.low,
  ci_high = df_fp$conf.high,
  estimate_col_name = "OR (95% CI)",
  xlim = c(.05, 3),
  null_line_at = 1,
  arrows = TRUE,
  x_scale_linear = FALSE,
  arrow_labels = c("Worse", "Better"),
  font_family = "sans",
  display = TRUE,
  nudge_x = .4,
  nudge_height = .06,
  stripe_colour = "#F5F5F5",
  file_path = "/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/CR_mv_plot_IPTW.png"
)

knitr::include_graphics("/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/CR_mv_plot_IPTW.png")
Show code
## Forest plot for MV PSM
df_fp <- mv_tab_PSM$table_body %>%
  select(header_row, label, N_obs, N_event, estimate, conf.low, conf.high, p.value, ) %>%
  mutate(
    label = ifelse(header_row == TRUE | is.na(header_row),as.character(label), paste0("     ", as.character(label)) ),
    p.value = signif(p.value, 2),
    `OR (95% CI)` = ifelse(
      is.na(estimate),"",paste0(round(estimate, 2), " (", round(conf.low,2), " to ",round(conf.high,2), ") ")
    )
  ) %>%
  rename(Characteristic = label,
         N = N_obs,
         Events = N_event,
         `p value` = p.value)
forester(
  left_side_data = df_fp[2],
  right_side_data = df_fp[9:8],
  estimate = df_fp$estimate,
  ci_low = df_fp$conf.low,
  ci_high = df_fp$conf.high,
  estimate_col_name = "OR (95% CI)",
  xlim = c(.05, 3),
  null_line_at = 1,
  arrows = TRUE,
  x_scale_linear = FALSE,
  arrow_labels = c("Worse", "Better"),
  font_family = "sans",
  display = TRUE,
  nudge_x = .4,
  nudge_height = .06,
  stripe_colour = "#F5F5F5",
  file_path = "/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/CR_mv_plot_PSM.png"
)

knitr::include_graphics("/Users/aportugu/Desktop/CD19 project/ASH abstract/forest/CR_mv_plot_PSM.png")

Toxicity

Logistic Model - ICANS grade 1+

Show code
theme_gtsummary_compact()
preds <- c("ICANS.any","Product", "LDH pre-LD","ALC pre-LD", "Largest lesion", "Age", "Male sex", "CMV", "Bridging category") 

data0 <- dataset %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    ICANS.any=ifelse(ICANS.grade == 0,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data1 <- IPTW.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    ICANS.any=ifelse(ICANS.grade == 0,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data2 <- m.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    ICANS.any=ifelse(ICANS.grade == 0,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

uv_tab <- tbl_uvregression(
  data0[c(preds)],
  method = glm,
  y = ICANS.any,
  method.args = list(family = binomial),
  exponentiate = TRUE
)


mv_tab<-glm( ICANS.any ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data0, family = binomial ) %>%
  tbl_regression(exponentiate=TRUE) 

uv_tab_IPTW <- tbl_uvregression(
  data1[c(preds)],
  method = glm,
  y = ICANS.any,
  method.args = list(family = binomial, weights = data1$weights),
  exponentiate = TRUE
)

mv_tab_IPTW<-glm( ICANS.any ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data1, family = binomial, weights=weights ) %>%
  tbl_regression(exponentiate=TRUE) 


uv_tab_PSM <- tbl_uvregression(
  data2[c(preds)],
  method = glm,
  y = ICANS.any,
  method.args = list(family = binomial, weights = data2$weights),
  exponentiate = TRUE
)

mv_tab_PSM<-glm( ICANS.any ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data2, family = binomial, weights=weights ) %>%
  tbl_regression(exponentiate=TRUE) 

row1 <- tbl_merge(list(uv_tab, mv_tab), tab_spanner = c("**Univariate**", "**Multivariable**"))
row2 <- tbl_merge(list(uv_tab_IPTW, mv_tab_IPTW))
row3 <- tbl_merge(list(uv_tab_PSM, mv_tab_PSM))
tbl_stack(list(row1, row2, row3), group_header = c("UNWEIGHTED ANALYSIS", "IPTW ANALYSIS", "PSM ANALYSIS"), quiet=TRUE)
Characteristic Univariate Multivariable
N OR1 95% CI1 p-value OR1 95% CI1 p-value
UNWEIGHTED ANALYSIS
Product 149





    Liso-cel


    Axi-cel
2.84 1.39, 6.06 0.005 3.08 1.28, 7.84 0.014
LDH pre-LD 148 12.9 2.57, 124 0.009 8.15 1.63, 68.9 0.024
ALC pre-LD 149 1.29 0.96, 2.17 0.3 1.81 1.04, 3.36 0.043
Largest lesion 149 1.18 1.07, 1.32 0.002 1.18 1.05, 1.33 0.009
Age 149 1.01 0.98, 1.04 0.5 1.03 1.00, 1.06 0.072
Male sex 149 1.56 0.80, 3.10 0.2 1.57 0.72, 3.51 0.3
CMV 149 14.5 5.90, 41.4 <0.001


Bridging category 145





    No bridging


    CR/PR
0.63 0.22, 1.67 0.4 0.71 0.22, 2.17 0.6
    SD/PD
1.57 0.72, 3.46 0.3 0.97 0.35, 2.62 >0.9
IPTW ANALYSIS
Product 126





    Liso-cel


    Axi-cel
1.75 0.82, 3.83 0.2 1.70 0.70, 4.28 0.2
LDH pre-LD 125 16.7 2.56, 239 0.014 11.2 1.73, 146 0.028
ALC pre-LD 126 1.41 0.96, 2.63 0.2 1.89 1.01, 3.88 0.059
Largest lesion 126 1.19 1.07, 1.35 0.002 1.20 1.06, 1.38 0.005
Age 126 1.01 0.98, 1.04 0.6 1.02 0.99, 1.06 0.3
Male sex 126 1.07 0.51, 2.25 0.9 1.15 0.49, 2.72 0.8
CMV 126 15.9 5.99, 51.0 <0.001


Bridging category 123





    No bridging


    CR/PR
0.60 0.20, 1.63 0.3 0.56 0.17, 1.72 0.3
    SD/PD
1.47 0.63, 3.48 0.4 0.76 0.25, 2.23 0.6
PSM ANALYSIS
Product 149





    Liso-cel


    Axi-cel
1.64 0.80, 3.51 0.2 1.65 0.67, 4.31 0.3
LDH pre-LD 148 25.1 3.27, 368 0.007 9.80 1.12, 175 0.076
ALC pre-LD 149 1.29 0.97, 2.22 0.3 2.12 1.17, 4.13 0.017
Largest lesion 149 1.28 1.13, 1.47 <0.001 1.28 1.11, 1.50 0.002
Age 149 0.97 0.93, 1.00 0.061 0.97 0.93, 1.01 0.2
Male sex 149 1.36 0.68, 2.79 0.4 1.10 0.48, 2.54 0.8
CMV 149 26.0 9.63, 86.1 <0.001


Bridging category 144





    No bridging


    CR/PR
0.49 0.15, 1.34 0.2 0.43 0.10, 1.43 0.2
    SD/PD
2.18 0.93, 5.19 0.073 0.78 0.23, 2.43 0.7
1 OR = Odds Ratio, CI = Confidence Interval

Logistic Model - ICANS grade 2+

Show code
theme_gtsummary_compact()
preds <- c("ICANS2.4","Product", "LDH pre-LD","ALC pre-LD", "Largest lesion", "Age", "Male sex", "Bridging category") 

data0 <- dataset %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    ICANS2.4=ifelse(ICANS.grade == 0 | ICANS.grade == 1 ,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data1 <- IPTW.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    ICANS2.4=ifelse(ICANS.grade == 0 | ICANS.grade == 1 ,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data2 <- m.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    ICANS2.4=ifelse(ICANS.grade == 0 | ICANS.grade == 1 ,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

uv_tab <- tbl_uvregression(
  data0[c(preds)],
  method = glm,
  y = ICANS2.4,
  method.args = list(family = binomial),
  exponentiate = TRUE
)


mv_tab<-glm( ICANS2.4 ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data0, family = binomial ) %>%
  tbl_regression(exponentiate=TRUE) 

uv_tab_IPTW <- tbl_uvregression(
  data1[c(preds)],
  method = glm,
  y = ICANS2.4,
  method.args = list(family = binomial, weights = data1$weights),
  exponentiate = TRUE
)

mv_tab_IPTW<-glm( ICANS2.4 ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD`+ `Bridging category`, data1, family = binomial, weights=weights ) %>%
  tbl_regression(exponentiate=TRUE) 


uv_tab_PSM <- tbl_uvregression(
  data2[c(preds)],
  method = glm,
  y = ICANS2.4,
  method.args = list(family = binomial, weights = data2$weights),
  exponentiate = TRUE
)

mv_tab_PSM<-glm( ICANS2.4 ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD`+ `Bridging category`, data2, family = binomial, weights=weights ) %>%
  tbl_regression(exponentiate=TRUE) 

row1 <- tbl_merge(list(uv_tab, mv_tab), tab_spanner = c("**Univariate**", "**Multivariable**"))
row2 <- tbl_merge(list(uv_tab_IPTW, mv_tab_IPTW))
row3 <- tbl_merge(list(uv_tab_PSM, mv_tab_PSM))
tbl_stack(list(row1, row2, row3), group_header = c("UNWEIGHTED ANALYSIS", "IPTW ANALYSIS", "PSM ANALYSIS"), quiet=TRUE)
Characteristic Univariate Multivariable
N OR1 95% CI1 p-value OR1 95% CI1 p-value
UNWEIGHTED ANALYSIS
Product 149





    Liso-cel


    Axi-cel
2.15 1.02, 4.75 0.050 1.88 0.78, 4.80 0.2
LDH pre-LD 148 6.62 1.82, 34.8 0.010 6.13 1.50, 35.0 0.021
ALC pre-LD 149 1.20 0.96, 1.92 0.3 1.49 0.95, 2.63 0.2
Largest lesion 149 1.15 1.04, 1.27 0.007 1.16 1.03, 1.31 0.019
Age 149 1.01 0.98, 1.04 0.5 1.03 0.99, 1.06 0.12
Male sex 149 1.81 0.89, 3.80 0.11 2.03 0.90, 4.78 0.095
Bridging category 145





    No bridging


    CR/PR
0.55 0.17, 1.55 0.3 0.60 0.16, 1.90 0.4
    SD/PD
1.25 0.56, 2.75 0.6 0.63 0.21, 1.70 0.4
IPTW ANALYSIS
Product 126





    Liso-cel


    Axi-cel
1.29 0.59, 2.91 0.5 1.09 0.44, 2.75 0.9
LDH pre-LD 125 8.14 1.81, 59.0 0.015 7.60 1.52, 58.2 0.026
ALC pre-LD 126 1.22 0.93, 2.15 0.4 1.55 0.91, 3.01 0.2
Largest lesion 126 1.17 1.05, 1.31 0.005 1.19 1.05, 1.36 0.009
Age 126 1.01 0.98, 1.04 0.7 1.01 0.98, 1.05 0.4
Male sex 126 1.31 0.61, 2.89 0.5 1.53 0.64, 3.83 0.3
Bridging category 123





    No bridging


    CR/PR
0.57 0.17, 1.65 0.3 0.54 0.14, 1.71 0.3
    SD/PD
1.25 0.52, 2.94 0.6 0.53 0.16, 1.57 0.3
PSM ANALYSIS
Product 149





    Liso-cel


    Axi-cel
1.67 0.79, 3.71 0.2 1.64 0.65, 4.46 0.3
LDH pre-LD 148 13.5 2.26, 137 0.012 6.27 0.89, 82.3 0.11
ALC pre-LD 149 1.24 0.97, 2.07 0.3 1.98 1.08, 3.75 0.028
Largest lesion 149 1.25 1.11, 1.43 <0.001 1.25 1.09, 1.46 0.003
Age 149 0.96 0.92, 1.00 0.032 0.96 0.92, 1.00 0.069
Male sex 149 1.47 0.71, 3.11 0.3 1.24 0.53, 2.96 0.6
Bridging category 144





    No bridging


    CR/PR
0.39 0.10, 1.17 0.12 0.33 0.07, 1.21 0.13
    SD/PD
1.95 0.82, 4.62 0.13 0.64 0.19, 1.99 0.5
1 OR = Odds Ratio, CI = Confidence Interval

Logistic Model - ICANS grade 3+

Show code
theme_gtsummary_compact()
preds <- c("ICANS3.4","Product", "LDH pre-LD","ALC pre-LD", "Largest lesion", "Age", "Male sex", "CMV", "Bridging category") 

data0 <- dataset %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    ICANS3.4=ifelse(ICANS.grade == 3 | ICANS.grade == 4,1,0),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data1 <- IPTW.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    ICANS3.4=ifelse(ICANS.grade == 3 | ICANS.grade == 4,1,0),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data2 <- m.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    ICANS3.4=ifelse(ICANS.grade == 3 | ICANS.grade == 4,1,0),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

uv_tab <- tbl_uvregression(
  data0[c(preds)],
  method = glm,
  y = ICANS3.4,
  method.args = list(family = binomial),
  exponentiate = TRUE
)

mv_tab<-glm( ICANS3.4 ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data0, family = binomial ) %>% tbl_regression(exponentiate=TRUE) 

uv_tab_IPTW <- tbl_uvregression(
  data1[c(preds)],
  method = glm,
  y = ICANS3.4,
  method.args = list(family = binomial, weights = data1$weights),
  exponentiate = TRUE
)

mv_tab_IPTW<-glm( ICANS3.4 ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data1, family = binomial, weights=weights ) %>%
  tbl_regression(exponentiate=TRUE) 

uv_tab_PSM <- tbl_uvregression(
  data2[c(preds)],
  method = glm,
  y = ICANS3.4,
  method.args = list(family = binomial, weights = data2$weights),
  exponentiate = TRUE
)

mv_tab_PSM<-glm( ICANS3.4 ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data2, family = binomial, weights=weights ) %>%
  tbl_regression(exponentiate=TRUE) 

row1 <- tbl_merge(list(uv_tab, mv_tab), tab_spanner = c("**Univariate**", "**Multivariable**"))
row2 <- tbl_merge(list(uv_tab_IPTW, mv_tab_IPTW))
row3 <- tbl_merge(list(uv_tab_PSM, mv_tab_PSM))
tbl_stack(list(row1, row2, row3), group_header = c("UNWEIGHTED ANALYSIS", "IPTW ANALYSIS", "PSM ANALYSIS"), quiet=TRUE)
Characteristic Univariate Multivariable
N OR1 95% CI1 p-value OR1 95% CI1 p-value
UNWEIGHTED ANALYSIS
Product 149





    Liso-cel


    Axi-cel
1.01 0.43, 2.54 >0.9 0.85 0.30, 2.45 0.8
LDH pre-LD 148 2.59 1.09, 8.63 0.12 2.58 1.08, 10.6 0.2
ALC pre-LD 149 0.97 0.59, 1.19 0.8 0.94 0.63, 1.15 0.6
Largest lesion 149 1.15 1.03, 1.29 0.012 1.15 1.01, 1.31 0.039
Age 149 1.02 0.98, 1.05 0.3 1.03 0.99, 1.08 0.2
Male sex 149 1.92 0.78, 5.20 0.2 2.82 1.01, 9.18 0.061
CMV 149 17.8 6.75, 54.0 <0.001


Bridging category 145





    No bridging


    CR/PR
1.36 0.35, 4.41 0.6 1.56 0.37, 5.69 0.5
    SD/PD
2.22 0.85, 5.67 0.10 1.33 0.40, 4.12 0.6
IPTW ANALYSIS
Product 126





    Liso-cel


    Axi-cel
0.60 0.24, 1.53 0.3 0.48 0.17, 1.37 0.2
LDH pre-LD 125 3.34 1.06, 13.6 0.075 3.65 1.09, 18.2 0.094
ALC pre-LD 126 0.97 0.55, 1.22 0.8 0.92 0.59, 1.16 0.5
Largest lesion 126 1.17 1.04, 1.32 0.008 1.15 1.01, 1.33 0.037
Age 126 1.00 0.97, 1.04 0.8 1.02 0.97, 1.06 0.5
Male sex 126 1.41 0.55, 3.91 0.5 2.08 0.71, 6.99 0.2
CMV 126 17.3 6.21, 56.2 <0.001


Bridging category 123





    No bridging


    CR/PR
1.28 0.33, 4.24 0.7 1.24 0.29, 4.50 0.8
    SD/PD
2.01 0.72, 5.47 0.2 0.94 0.24, 3.20 >0.9
PSM ANALYSIS
Product 149





    Liso-cel


    Axi-cel
0.95 0.40, 2.41 >0.9 0.83 0.30, 2.38 0.7
LDH pre-LD 148 5.02 1.04, 28.6 0.051 2.95 0.62, 22.9 0.3
ALC pre-LD 149 0.99 0.65, 1.21 >0.9 0.94 0.68, 1.16 0.6
Largest lesion 149 1.21 1.07, 1.38 0.003 1.17 1.02, 1.35 0.028
Age 149 0.97 0.93, 1.01 0.13 0.98 0.93, 1.03 0.4
Male sex 149 1.70 0.70, 4.55 0.3 1.54 0.57, 4.50 0.4
CMV 149 12.6 4.95, 34.4 <0.001


Bridging category 144





    No bridging


    CR/PR
0.89 0.21, 2.97 0.9 0.81 0.18, 2.92 0.8
    SD/PD
2.50 0.92, 6.60 0.067 1.03 0.28, 3.44 >0.9
1 OR = Odds Ratio, CI = Confidence Interval

Logistic Model - CRS grade 1+

Show code
theme_gtsummary_compact()
preds <- c("CRS.any","Product", "LDH pre-LD","ALC pre-LD", "Largest lesion", "Age", "Male sex", "CMV", "Bridging category") 

data0 <- dataset %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS.any=ifelse(CRS.grade == 0,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data1 <- IPTW.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS.any=ifelse(CRS.grade == 0,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data2 <- m.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS.any=ifelse(CRS.grade == 0,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

uv_tab <- tbl_uvregression(
  data0[c(preds)],
  method = glm,
  y = CRS.any,
  method.args = list(family = binomial),
  exponentiate = TRUE
)

mv_tab<-glm( CRS.any ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data0, family = binomial ) %>% tbl_regression(exponentiate=TRUE) 

uv_tab_IPTW <- tbl_uvregression(
  data1[c(preds)],
  method = glm,
  y = CRS.any,
  method.args = list(family = binomial, weights = data1$weights),
  exponentiate = TRUE
)

mv_tab_IPTW<-glm( CRS.any ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data1, family = binomial, weights=weights ) %>%
  tbl_regression(exponentiate=TRUE) 

uv_tab_PSM <- tbl_uvregression(
  data2[c(preds)],
  method = glm,
  y = CRS.any,
  method.args = list(family = binomial, weights = data2$weights),
  exponentiate = TRUE
)

mv_tab_PSM<-glm( CRS.any ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data2, family = binomial, weights=weights ) %>%
  tbl_regression(exponentiate=TRUE) 

row1 <- tbl_merge(list(uv_tab, mv_tab), tab_spanner = c("**Univariate**", "**Multivariable**"))
row2 <- tbl_merge(list(uv_tab_IPTW, mv_tab_IPTW))
row3 <- tbl_merge(list(uv_tab_PSM, mv_tab_PSM))
tbl_stack(list(row1, row2, row3), group_header = c("UNWEIGHTED ANALYSIS", "IPTW ANALYSIS", "PSM ANALYSIS"), quiet=TRUE)
Characteristic Univariate Multivariable
N OR1 95% CI1 p-value OR1 95% CI1 p-value
UNWEIGHTED ANALYSIS
Product 149





    Liso-cel


    Axi-cel
4.50 1.95, 10.8 <0.001 4.71 1.60, 14.9 0.006
LDH pre-LD 148 89.4 2.31, 25,644 0.065 89.0 1.37, 47,171 0.10
ALC pre-LD 149 1.69 0.94, 4.14 0.2 3.35 1.37, 11.8 0.028
Largest lesion 149 1.28 1.09, 1.56 0.006 1.30 1.09, 1.61 0.007
Age 149 0.98 0.94, 1.01 0.2 0.99 0.94, 1.03 0.5
Male sex 149 0.85 0.35, 1.95 0.7 0.52 0.17, 1.46 0.2
CMV 149 14.0 2.82, 254 0.011


Bridging category 145





    No bridging


    CR/PR
0.28 0.10, 0.83 0.019 0.23 0.06, 0.85 0.027
    SD/PD
0.72 0.27, 2.07 0.5 0.30 0.08, 1.08 0.065
IPTW ANALYSIS
Product 126





    Liso-cel


    Axi-cel
2.69 1.12, 6.54 0.027 3.89 1.26, 13.1 0.021
LDH pre-LD 125 667 5.16, 671,492 0.033 433 2.95, 533,357 0.051
ALC pre-LD 126 2.05 0.96, 5.88 0.13 3.30 1.20, 14.0 0.057
Largest lesion 126 1.26 1.07, 1.53 0.012 1.30 1.09, 1.62 0.007
Age 126 0.97 0.93, 1.01 0.2 0.98 0.93, 1.02 0.3
Male sex 126 0.53 0.18, 1.34 0.2 0.33 0.08, 1.07 0.080
CMV 126 22.5 3.52, 1,160 0.014


Bridging category 123





    No bridging


    CR/PR
0.22 0.07, 0.67 0.007 0.16 0.04, 0.63 0.010
    SD/PD
0.68 0.23, 2.14 0.5 0.24 0.06, 1.00 0.052
PSM ANALYSIS
Product 149





    Liso-cel


    Axi-cel
2.11 0.99, 4.49 0.053 3.53 1.27, 10.5 0.018
LDH pre-LD 148 126 3.12, 21,564 0.034 522 5.46, 178,178 0.018
ALC pre-LD 149 3.62 1.54, 9.78 0.006 4.78 1.78, 18.6 0.010
Largest lesion 149 1.21 1.05, 1.45 0.018 1.29 1.08, 1.59 0.009
Age 149 1.00 0.96, 1.04 >0.9 0.99 0.94, 1.04 0.7
Male sex 149 0.34 0.14, 0.77 0.013 0.22 0.07, 0.65 0.009
CMV 149 16.7 3.40, 303 0.006


Bridging category 144





    No bridging


    CR/PR
0.17 0.06, 0.44 <0.001 0.16 0.04, 0.52 0.003
    SD/PD
0.81 0.30, 2.39 0.7 0.51 0.13, 1.98 0.3
1 OR = Odds Ratio, CI = Confidence Interval

Logistic Model - CRS grade 2+

Show code
theme_gtsummary_compact()
preds <- c("CRS2.4","Product", "LDH pre-LD","ALC pre-LD", "Largest lesion", "Age", "Male sex", "CMV", "Bridging category") 

data0 <- dataset %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS2.4=ifelse(CRS.grade == 0 | CRS.grade == 1 ,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data1 <- IPTW.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS2.4=ifelse(CRS.grade == 0 | CRS.grade == 1 ,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data2 <- m.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS2.4=ifelse(CRS.grade == 0 | CRS.grade == 1 ,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

uv_tab <- tbl_uvregression(
  data0[c(preds)],
  method = glm,
  y = CRS2.4,
  method.args = list(family = binomial),
  exponentiate = TRUE
)

mv_tab<-glm( CRS2.4 ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data0, family = binomial ) %>% tbl_regression(exponentiate=TRUE) 

uv_tab_IPTW <- tbl_uvregression(
  data1[c(preds)],
  method = glm,
  y = CRS2.4,
  method.args = list(family = binomial, weights = data1$weights),
  exponentiate = TRUE
)

mv_tab_IPTW<-glm( CRS2.4 ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data1, family = binomial, weights=weights ) %>%
  tbl_regression(exponentiate=TRUE) 

uv_tab_PSM <- tbl_uvregression(
  data2[c(preds)],
  method = glm,
  y = CRS2.4,
  method.args = list(family = binomial, weights = data2$weights),
  exponentiate = TRUE
)

mv_tab_PSM<-glm( CRS2.4 ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data2, family = binomial, weights=weights ) %>%
  tbl_regression(exponentiate=TRUE) 

row1 <- tbl_merge(list(uv_tab, mv_tab), tab_spanner = c("**Univariate**", "**Multivariable**"))
row2 <- tbl_merge(list(uv_tab_IPTW, mv_tab_IPTW))
row3 <- tbl_merge(list(uv_tab_PSM, mv_tab_PSM))
tbl_stack(list(row1, row2, row3), group_header = c("UNWEIGHTED ANALYSIS", "IPTW ANALYSIS", "PSM ANALYSIS"), quiet=TRUE)
Characteristic Univariate Multivariable
N OR1 95% CI1 p-value OR1 95% CI1 p-value
UNWEIGHTED ANALYSIS
Product 149





    Liso-cel


    Axi-cel
4.08 1.90, 9.46 <0.001 4.25 1.79, 11.0 0.002
LDH pre-LD 148 0.96 0.59, 1.29 0.8 0.88 0.47, 1.20 0.5
ALC pre-LD 149 0.94 0.66, 1.14 0.6 0.98 0.72, 1.19 0.9
Largest lesion 149 1.08 0.98, 1.19 0.11 1.08 0.97, 1.20 0.2
Age 149 0.99 0.96, 1.01 0.3 1.00 0.97, 1.03 >0.9
Male sex 149 0.84 0.43, 1.66 0.6 0.69 0.32, 1.45 0.3
CMV 149 2.13 1.03, 4.46 0.042


Bridging category 145





    No bridging


    CR/PR
1.14 0.42, 2.97 0.8 1.68 0.57, 4.98 0.3
    SD/PD
1.21 0.55, 2.65 0.6 1.18 0.47, 2.96 0.7
IPTW ANALYSIS
Product 126





    Liso-cel


    Axi-cel
3.07 1.36, 7.45 0.009 3.19 1.32, 8.36 0.013
LDH pre-LD 125 1.00 0.58, 1.53 >0.9 0.91 0.47, 1.38 0.6
ALC pre-LD 126 0.97 0.67, 1.21 0.8 0.98 0.69, 1.24 0.9
Largest lesion 126 1.06 0.96, 1.17 0.3 1.07 0.95, 1.20 0.2
Age 126 0.99 0.96, 1.02 0.5 1.00 0.96, 1.03 0.8
Male sex 126 0.58 0.27, 1.21 0.15 0.49 0.21, 1.09 0.083
CMV 126 2.36 1.08, 5.22 0.032


Bridging category 123





    No bridging


    CR/PR
0.99 0.35, 2.69 >0.9 1.09 0.37, 3.17 0.9
    SD/PD
1.16 0.49, 2.73 0.7 1.04 0.38, 2.84 >0.9
PSM ANALYSIS
Product 149





    Liso-cel


    Axi-cel
3.86 1.79, 8.95 <0.001 5.14 2.05, 14.3 <0.001
LDH pre-LD 148 1.20 0.40, 5.14 0.7 0.98 0.27, 6.34 >0.9
ALC pre-LD 149 1.00 0.78, 1.21 >0.9 0.97 0.73, 1.19 0.8
Largest lesion 149 1.00 0.90, 1.11 >0.9 1.02 0.89, 1.17 0.7
Age 149 1.00 0.96, 1.03 >0.9 0.99 0.94, 1.03 0.6
Male sex 149 0.27 0.13, 0.54 <0.001 0.17 0.07, 0.39 <0.001
CMV 149 2.11 0.98, 4.59 0.058


Bridging category 144





    No bridging


    CR/PR
0.25 0.07, 0.72 0.017 0.39 0.11, 1.22 0.13
    SD/PD
0.90 0.38, 2.09 0.8 1.38 0.45, 4.23 0.6
1 OR = Odds Ratio, CI = Confidence Interval

Logistic Model - CRS grade 3+

Show code
theme_gtsummary_compact()
preds <- c("CRS3.4","Product", "LDH pre-LD","ALC pre-LD", "Largest lesion", "Age", "Male sex", "CMV", "Bridging category") 

data0 <- dataset %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS3.4=ifelse(CRS.grade == 3 | CRS.grade == 4,1,0),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data1 <- IPTW.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS3.4=ifelse(CRS.grade == 3 | CRS.grade == 4,1,0),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data2 <- m.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS3.4=ifelse(CRS.grade == 3 | CRS.grade == 4,1,0),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

uv_tab <- tbl_uvregression(
  data0[c(preds)],
  method = glm,
  y = CRS3.4,
  method.args = list(family = binomial),
  exponentiate = TRUE
)

mv_tab<-glm( CRS3.4 ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data0, family = binomial ) %>% tbl_regression(exponentiate=TRUE) 

uv_tab_IPTW <- tbl_uvregression(
  data1[c(preds)],
  method = glm,
  y = CRS3.4,
  method.args = list(family = binomial, weights = data1$weights),
  exponentiate = TRUE
)

mv_tab_IPTW<-glm( CRS3.4 ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data1, family = binomial, weights=weights ) %>%
  tbl_regression(exponentiate=TRUE) 

uv_tab_PSM <- tbl_uvregression(
  data2[c(preds)],
  method = glm,
  y = CRS3.4,
  method.args = list(family = binomial, weights = data2$weights),
  exponentiate = TRUE
)

mv_tab_PSM<-glm( CRS3.4 ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data2, family = binomial, weights=weights ) %>%
  tbl_regression(exponentiate=TRUE) 

row1 <- tbl_merge(list(uv_tab, mv_tab), tab_spanner = c("**Univariate**", "**Multivariable**"))
row2 <- tbl_merge(list(uv_tab_IPTW, mv_tab_IPTW))
row3 <- tbl_merge(list(uv_tab_PSM, mv_tab_PSM))
tbl_stack(list(row1, row2, row3), group_header = c("UNWEIGHTED ANALYSIS", "IPTW ANALYSIS", "PSM ANALYSIS"), quiet=TRUE)
Characteristic Univariate Multivariable
N OR1 95% CI1 p-value OR1 95% CI1 p-value
UNWEIGHTED ANALYSIS
Product 149





    Liso-cel


    Axi-cel
4.31 0.76, 81.1 0.2 2.87 0.45, 56.2 0.3
LDH pre-LD 148 1.10 0.53, 1.50 0.6 1.10 0.52, 1.57 0.6
ALC pre-LD 149 0.66 0.13, 1.20 0.5 0.62 0.11, 1.31 0.5
Largest lesion 149 1.02 0.83, 1.21 0.8 0.99 0.78, 1.22 >0.9
Age 149 0.98 0.94, 1.04 0.5 1.00 0.95, 1.06 >0.9
Male sex 149 2.20 0.51, 15.1 0.3 2.09 0.45, 16.5 0.4
CMV 149 2.23 0.53, 8.86 0.3


Bridging category 145





    No bridging


    CR/PR
0.00
>0.9 0.00
>0.9
    SD/PD
0.68 0.10, 2.99 0.6 0.68 0.08, 3.61 0.7
IPTW ANALYSIS
Product 126





    Liso-cel


    Axi-cel
2.70 0.50, 35.6 0.3 2.07 0.36, 28.1 0.5
LDH pre-LD 125 1.10
0.7 1.15 0.42, 1.80 0.6
ALC pre-LD 126 0.86 0.18, 1.30 0.8 0.71 0.12, 1.39 0.7
Largest lesion 126 0.98 0.77, 1.18 0.9 0.97 0.73, 1.22 0.8
Age 126 0.99 0.94, 1.06 0.8 1.00 0.94, 1.07 >0.9
Male sex 126 2.38 0.47, 23.8 0.4 2.31 0.42, 27.0 0.4
CMV 126 1.99 0.42, 8.67 0.4


Bridging category 123





    No bridging


    CR/PR
0.00
>0.9 0.00
>0.9
    SD/PD
0.50 0.05, 2.57 0.5 0.55 0.04, 3.55 0.6
PSM ANALYSIS
Product 149





    Liso-cel


    Axi-cel
2.21 0.32, 43.6 0.5 1.72 0.22, 37.4 0.6
LDH pre-LD 148 1.17
0.8 1.28
0.6
ALC pre-LD 149 1.02
>0.9 1.10
0.7
Largest lesion 149 0.91 0.60, 1.19 0.6 0.89 0.53, 1.26 0.6
Age 149 0.99 0.91, 1.10 0.9 0.98 0.90, 1.10 0.8
Male sex 149 0.95 0.16, 7.09 >0.9 1.24 0.19, 10.6 0.8
CMV 149 1.76 0.21, 10.5 0.5


Bridging category 144





    No bridging


    CR/PR
0.00
>0.9 0.00
>0.9
    SD/PD
0.27 0.00, 2.87 0.4 0.27 0.00, 4.48 0.5
1 OR = Odds Ratio, CI = Confidence Interval

Medication administration

Tocilizumab

Show code
theme_gtsummary_compact()
preds <- c("toci.doses","Product", "LDH pre-LD","ALC pre-LD", "Largest lesion", "Age", "Male sex", "CMV", "Bridging category") 

data0 <- dataset %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS2.4=ifelse(CRS.grade == 0 | CRS.grade == 1 ,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data1 <- IPTW.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS2.4=ifelse(CRS.grade == 0 | CRS.grade == 1 ,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data2 <- m.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS2.4=ifelse(CRS.grade == 0 | CRS.grade == 1 ,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

uv_tab <- tbl_uvregression(
  data0[c(preds)],
  method = lm,
  y = toci.doses
)

mv_tab<-lm( toci.doses ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data0) %>% tbl_regression() 

uv_tab_IPTW <- tbl_uvregression(
  data1[c(preds)],
  method = lm,
  y = toci.doses,
  method.args = list(weights = data1$weights)
)

mv_tab_IPTW<-lm( toci.doses ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data1, weights=weights ) %>%
  tbl_regression() 

uv_tab_PSM <- tbl_uvregression(
  data2[c(preds)],
  method = lm,
  y = toci.doses,
  method.args = list(weights = data2$weights)
)

mv_tab_PSM<-lm( toci.doses ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data2, weights=weights ) %>%
  tbl_regression() 

row1 <- tbl_merge(list(uv_tab, mv_tab), tab_spanner = c("**Univariate**", "**Multivariable**"))
row2 <- tbl_merge(list(uv_tab_IPTW, mv_tab_IPTW))
row3 <- tbl_merge(list(uv_tab_PSM, mv_tab_PSM))
tbl_stack(list(row1, row2, row3), group_header = c("UNWEIGHTED ANALYSIS", "IPTW ANALYSIS", "PSM ANALYSIS"), quiet=TRUE)
Characteristic Univariate Multivariable
N Beta 95% CI1 p-value Beta 95% CI1 p-value
UNWEIGHTED ANALYSIS
Product 149





    Liso-cel


    Axi-cel
0.58 0.21, 0.95 0.002 0.37 -0.05, 0.78 0.080
LDH pre-LD 148 0.17 0.02, 0.32 0.027 0.13 -0.02, 0.28 0.093
ALC pre-LD 149 -0.04 -0.14, 0.05 0.4 -0.04 -0.13, 0.06 0.4
Largest lesion 149 0.07 0.02, 0.12 0.004 0.06 0.01, 0.11 0.026
Age 149 -0.01 -0.03, 0.00 0.049 -0.01 -0.02, 0.01 0.5
Male sex 149 0.05 -0.32, 0.43 0.8 0.01 -0.36, 0.39 >0.9
CMV 149 1.1 0.77, 1.5 <0.001


Bridging category 145





    No bridging


    CR/PR
-0.50 -1.0, 0.03 0.064 -0.35 -0.88, 0.17 0.2
    SD/PD
0.30 -0.13, 0.73 0.2 0.08 -0.38, 0.55 0.7
IPTW ANALYSIS
Product 126





    Liso-cel


    Axi-cel
0.36 -0.02, 0.73 0.062 0.25 -0.14, 0.65 0.2
LDH pre-LD 125 0.18 0.01, 0.35 0.036 0.14 -0.03, 0.32 0.10
ALC pre-LD 126 -0.04 -0.14, 0.06 0.5 -0.04 -0.14, 0.06 0.4
Largest lesion 126 0.06 0.01, 0.11 0.017 0.05 0.00, 0.10 0.049
Age 126 -0.01 -0.03, 0.00 0.10 -0.01 -0.02, 0.01 0.4
Male sex 126 -0.06 -0.43, 0.32 0.8 -0.07 -0.44, 0.31 0.7
CMV 126 1.1 0.77, 1.5 <0.001


Bridging category 123





    No bridging


    CR/PR
-0.49 -0.98, 0.01 0.053 -0.45 -0.94, 0.05 0.076
    SD/PD
0.24 -0.18, 0.66 0.3 0.02 -0.45, 0.48 >0.9
PSM ANALYSIS
Product 149





    Liso-cel


    Axi-cel
0.40 0.08, 0.72 0.015 0.34 0.00, 0.68 0.052
LDH pre-LD 148 0.31 -0.07, 0.69 0.11 0.21 -0.19, 0.60 0.3
ALC pre-LD 149 0.00 -0.08, 0.08 >0.9 -0.01 -0.09, 0.08 0.8
Largest lesion 149 0.04 -0.01, 0.09 0.084 0.03 -0.03, 0.08 0.3
Age 149 -0.01 -0.03, 0.00 0.077 -0.01 -0.03, 0.01 0.2
Male sex 149 -0.07 -0.39, 0.25 0.7 -0.16 -0.48, 0.17 0.3
CMV 149 1.1 0.81, 1.4 <0.001


Bridging category 144





    No bridging


    CR/PR
-0.59 -1.0, -0.17 0.006 -0.51 -0.93, -0.08 0.020
    SD/PD
0.23 -0.17, 0.62 0.3 0.10 -0.36, 0.55 0.7
1 CI = Confidence Interval

Cefepime

Show code
theme_gtsummary_compact()
preds <- c("cefepime.doses","Product", "LDH pre-LD","ALC pre-LD", "Largest lesion", "Age", "Male sex", "CMV", "Bridging category") 

data0 <- dataset %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS2.4=ifelse(CRS.grade == 0 | CRS.grade == 1 ,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data1 <- IPTW.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS2.4=ifelse(CRS.grade == 0 | CRS.grade == 1 ,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

data2 <- m.data %>%
  mutate(
    Product = factor(recode(CAR.T.Product.Type, "Yescarta" = "Axi-cel","Breyanzi" = "Liso-cel"), levels = c("Liso-cel","Axi-cel") ),
    "Largest lesion" = Largest.lesion,
    "HCT-CI" = HCT.CI,
    "ALC pre-LD" = ALC.preLD,
    "LDH pre-LD" = LDH.preLD/1000,
    "Male sex" = ifelse(Sex == "M",1,0),
    CRS2.4=ifelse(CRS.grade == 0 | CRS.grade == 1 ,0,1),
    "Bridging category" = factor(recode(Bridging.response.category, "0" = "No bridging", "1" = "CR/PR", "2" = "SD/PD"), levels = c("No bridging","CR/PR","SD/PD"))
  )

uv_tab <- tbl_uvregression(
  data0[c(preds)],
  method = lm,
  y = cefepime.doses
)

mv_tab<-lm( cefepime.doses ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data0) %>% tbl_regression() 

uv_tab_IPTW <- tbl_uvregression(
  data1[c(preds)],
  method = lm,
  y = cefepime.doses,
  method.args = list(weights = data1$weights)
)

mv_tab_IPTW<-lm( cefepime.doses ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data1, weights=weights ) %>%
  tbl_regression() 

uv_tab_PSM <- tbl_uvregression(
  data2[c(preds)],
  method = lm,
  y = cefepime.doses,
  method.args = list(weights = data2$weights)
)

mv_tab_PSM<-lm( cefepime.doses ~ Product + `Largest lesion` + `ALC pre-LD` + Age + `Male sex` + `LDH pre-LD` + `Bridging category`, data2, weights=weights ) %>%
  tbl_regression() 

row1 <- tbl_merge(list(uv_tab, mv_tab), tab_spanner = c("**Univariate**", "**Multivariable**"))
row2 <- tbl_merge(list(uv_tab_IPTW, mv_tab_IPTW))
row3 <- tbl_merge(list(uv_tab_PSM, mv_tab_PSM))
tbl_stack(list(row1, row2, row3), group_header = c("UNWEIGHTED ANALYSIS", "IPTW ANALYSIS", "PSM ANALYSIS"), quiet=TRUE)
Characteristic Univariate Multivariable
N Beta 95% CI1 p-value Beta 95% CI1 p-value
UNWEIGHTED ANALYSIS
Product 149





    Liso-cel


    Axi-cel
4.9 2.0, 7.8 <0.001 4.8 1.5, 8.0 0.005
LDH pre-LD 148 1.2 0.02, 2.4 0.046 0.95 -0.24, 2.2 0.12
ALC pre-LD 149 0.58 -0.17, 1.3 0.13 0.79 0.03, 1.5 0.041
Largest lesion 149 0.19 -0.21, 0.60 0.3 0.06 -0.36, 0.49 0.8
Age 149 -0.11 -0.21, 0.00 0.056 -0.06 -0.17, 0.06 0.3
Male sex 149 1.2 -1.8, 4.1 0.4 1.7 -1.3, 4.6 0.3
CMV 149 3.4 0.26, 6.5 0.034


Bridging category 145





    No bridging


    CR/PR
0.31 -3.9, 4.6 0.9 2.0 -2.1, 6.2 0.3
    SD/PD
1.2 -2.2, 4.7 0.5 0.99 -2.7, 4.6 0.6
IPTW ANALYSIS
Product 126





    Liso-cel


    Axi-cel
4.0 1.1, 7.0 0.008 3.9 0.72, 7.1 0.017
LDH pre-LD 125 1.3 -0.03, 2.7 0.056 1.1 -0.28, 2.5 0.12
ALC pre-LD 126 0.62 -0.19, 1.4 0.13 0.78 -0.03, 1.6 0.060
Largest lesion 126 0.08 -0.32, 0.47 0.7 0.06 -0.37, 0.48 0.8
Age 126 -0.08 -0.19, 0.04 0.2 -0.07 -0.19, 0.05 0.2
Male sex 126 0.28 -2.7, 3.3 0.9 0.94 -2.1, 4.0 0.5
CMV 126 3.4 0.29, 6.4 0.032


Bridging category 123





    No bridging


    CR/PR
0.09 -4.0, 4.1 >0.9 1.0 -3.0, 5.0 0.6
    SD/PD
-0.04 -3.5, 3.4 >0.9 -0.27 -4.0, 3.5 0.9
PSM ANALYSIS
Product 149





    Liso-cel


    Axi-cel
3.8 1.0, 6.6 0.008 4.0 0.96, 7.0 0.010
LDH pre-LD 148 3.8 0.44, 7.1 0.027 2.8 -0.64, 6.3 0.11
ALC pre-LD 149 0.71 0.00, 1.4 0.051 0.83 0.09, 1.6 0.028
Largest lesion 149 0.16 -0.27, 0.59 0.5 -0.01 -0.47, 0.45 >0.9
Age 149 -0.11 -0.25, 0.03 0.14 -0.11 -0.26, 0.04 0.2
Male sex 149 1.1 -1.7, 3.9 0.4 1.2 -1.7, 4.0 0.4
CMV 149 4.9 1.8, 8.0 0.002


Bridging category 144





    No bridging


    CR/PR
-1.5 -5.3, 2.3 0.4 -0.85 -4.6, 2.9 0.7
    SD/PD
0.45 -3.1, 4.0 0.8 -0.44 -4.4, 3.6 0.8
1 CI = Confidence Interval

PROBABILITY PLOTS

Response based on labs and imaging

Probability of CR: LDH pre-LD, stratified by product

Show code
data1 <- filter(dataset, Infused == 1) %>%
  mutate(
    CAR.T.Product.Type = recode(CAR.T.Product.Type, "Breyanzi"="Liso-cel","Yescarta"="Axi-cel")
  )

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(Best.CR ~ CAR.T.Product.Type * LDH.preLD, data=data1)

data.frame(Predict(fit,LDH.preLD,CAR.T.Product.Type,fun = plogis)) %>%
  ggplot() +
  geom_line(aes(x=LDH.preLD,y=yhat,col=CAR.T.Product.Type)) +
  geom_ribbon(aes(x=LDH.preLD,ymin=lower, ymax=upper,fill=CAR.T.Product.Type),alpha=0.10)+
  labs(x = "LDH pre-LD (U/L)",
       y = "Probability of CR")+
  #scale_x_continuous(labels = alc_breaks,breaks = c(-.5,-.25,0,.25))+
  #ggtitle("Figure.")+
  theme_bw() +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank()) + 
  ylim(0,1)

Probability of CR: largest lesion, stratified by product

Show code
data1 <- filter(dataset, Infused == 1) %>%
  mutate(
    CAR.T.Product.Type = recode(CAR.T.Product.Type, "Breyanzi"="Liso-cel","Yescarta"="Axi-cel")
  )

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(Best.CR ~ CAR.T.Product.Type*Largest.lesion, data=data1)

data.frame(Predict(fit,Largest.lesion,CAR.T.Product.Type,fun = plogis)) %>%
  ggplot() +
  geom_line(aes(x=Largest.lesion,y=yhat,col=CAR.T.Product.Type)) +
  geom_ribbon(aes(x=Largest.lesion,ymin=lower, ymax=upper,fill=CAR.T.Product.Type),alpha=0.10)+
  labs(x = "Largest lesion (cm)",
       y = "Probability of CR")+
  #scale_x_continuous(labels = alc_breaks,breaks = c(-.5,-.25,0,.25))+
  #ggtitle("Figure.")+
  theme_bw() +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank()) + 
  ylim(0,1)

Probability of CR and PD: ALC (RCS)

Show code
data1 <- filter(dataset, Infused == 1)

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(Best.CR ~ rcs(ALC.preLD,3), data=data1)
df1 <- data.frame(Predict(fit,ALC.preLD,fun = plogis))

fit2 <- lrm(Best.PD ~ rcs(ALC.preLD,3), data=data1)
df2 <- data.frame(Predict(fit2,ALC.preLD,fun = plogis))

ggplot() + 
  geom_line(data=df1, aes(x=ALC.preLD,y=yhat, color = "CR")) + geom_ribbon( data=df1, aes(x=ALC.preLD,ymin=lower, ymax=upper),alpha=0.10)+
  geom_line(data=df2, aes(x=ALC.preLD,y=yhat, color ="PD" )) + geom_ribbon(data = df2, aes(x=ALC.preLD,ymin=lower, ymax=upper),alpha=0.10)+
  labs(x = "ALC pre-LD (10\U00B3/\U00B5L)",
       y = "Probability")+
  theme_bw() +
  scale_y_continuous(breaks=c(0,0.2,0.4,0.6,0.8,1.0), limits=c(0, 1)) + 
  scale_x_continuous(breaks=c(0.25,0.5,0.75,1.0,1.25,1.5,1.75), limits=c(0.25, 1.75)) + 
  theme(legend.position = c(0, 1),legend.justification = c(-9, 1.1))+
  scale_color_manual(values = c ("steelblue","coral2")) + 
  theme(title = element_text(size=20,face="bold"),legend.title=element_blank())

Hazard of PFS: LDH pre-LD

Show code
data1 <- filter(dataset, Infused == 1)

S <- Surv(data1$Days.to.relapse.death.or.DLC, data1$Relapse.or.death)
f <- cph(S ~ LDH.preLD * CAR.T.Product.Type, x=TRUE, y=TRUE,surv=TRUE,data=data1)

model <- Predict(f, CAR.T.Product.Type, LDH.preLD, fun=function(x) exp(x) )

ggplot(as.data.frame(model),aes(x=LDH.preLD, y=yhat, z = CAR.T.Product.Type)) + 
  geom_line(
    aes(col = CAR.T.Product.Type)
  ) + 
  geom_ribbon(data = model, aes(ymin=lower, ymax=upper), alpha=0.2, linetype=0) + 
  theme_bw() + 
  labs(
    #title = "Survival by product and LDH pre-LD",
    x = "LDH pre-LD (U/L)",
    y = "PFS (hazard)") +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Probability of CR and PD: LDH pre-LD

Show code
data1 <- filter(dataset, Infused == 1)

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(Best.CR ~ LDH.preLD, data=data1)

df1 <- data.frame(Predict(fit,LDH.preLD,fun = plogis))



fit2 <- lrm(Best.PD ~ LDH.preLD, data=data1)
df2 <- data.frame(Predict(fit2,LDH.preLD,fun = plogis))

ggplot() + 
  geom_line(data=df1, aes(x=LDH.preLD,y=yhat, color = "CR")) + geom_ribbon( data=df1, aes(x=LDH.preLD,ymin=lower, ymax=upper),alpha=0.10)+
  geom_line(data=df2, aes(x=LDH.preLD,y=yhat, color ="PD" )) + geom_ribbon(data = df2, aes(x=LDH.preLD,ymin=lower, ymax=upper),alpha=0.10)+
  labs(x = "LDH pre-LD (U/L)",
       y = "Probability")+
  theme_classic() +
  scale_y_continuous(breaks=c(0,0.2,0.4,0.6,0.8,1.0), limits=c(0, 1)) + 
  #scale_x_continuous(breaks=c(0.25,0.5,0.75,1.0,1.25,1.5,1.75), limits=c(0.25, 1.75)) + 
  theme(legend.position = c(0, 1),legend.justification = c(-9, 1.1))+
  scale_color_manual(values = c ("steelblue","coral2")) + 
  theme(title = element_text(size=20,face="bold"),legend.title=element_blank())

Probability of CR: LDH pre-LD

Show code
data1 <- filter(dataset, Infused == 1)

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(Best.CR ~ rcs(LDH.preLD,3), data=data1)

data.frame(Predict(fit,LDH.preLD,fun = plogis)) %>%
  ggplot() +
  geom_line(aes(x=LDH.preLD,y=yhat)) +
  geom_ribbon(aes(x=LDH.preLD,ymin=lower, ymax=upper),alpha=0.10)+
  labs(x = "LDH pre-LD (U/L)",
       y = "Probability of CR")+
  #scale_x_continuous(labels = alc_breaks,breaks = c(-.5,-.25,0,.25))+
  #ggtitle("Figure.")+
  ylim(0,1) +
  theme_classic() +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Probability of CR: largest Lesion size, stratified by product

Show code
data1 <- filter(dataset, Infused == 1)

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(Best.CR ~ CAR.T.Product.Type * rcs(Largest.lesion,3), data=data1)

data.frame(Predict(fit,Largest.lesion,CAR.T.Product.Type,fun = plogis)) %>%
  ggplot() +
  geom_line(aes(x=Largest.lesion ,y=yhat,col=CAR.T.Product.Type)) +
  geom_ribbon(aes(x=Largest.lesion ,ymin=lower, ymax=upper,fill=CAR.T.Product.Type),alpha=0.10)+
  labs(x = "Largest lesion (cm)",
       y = "Probability of CR")+
  theme_bw() +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Probability of CR: Largest Lesion size (RCS)

Show code
data1 <- filter(dataset, Infused == 1)

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(Best.CR ~ rcs(Largest.lesion,3), data=data1)

data.frame(Predict(fit,Largest.lesion,fun = plogis)) %>%
  ggplot() +
  geom_line(aes(x=Largest.lesion ,y=yhat)) +
  geom_ribbon(aes(x=Largest.lesion ,ymin=lower, ymax=upper),alpha=0.10)+
  labs(x = "Largest lesion (cm)",
       y = "Probability of CR")+
  ylim(0,1) +
  theme_classic() +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Ferritin!

Probability of ICANS based on day 3 ferritin

Show code
data1 <- filter(dataset, Infused == 1) %>%
  mutate(
    ICANS0 = ifelse( ICANS.grade==0,1,0),
    ICANS1.2 = ifelse( ICANS.grade==1 | ICANS.grade == 2,1,0),
    ICANS.any.grade = ifelse( ICANS.grade != 0 ,1,0),
    ICANS3.4 = ifelse( ICANS.grade==3 | ICANS.grade == 4,1,0),
    ferritin.ratio = log(ferritin.d3 / ferritin.d0),
    ferritin.d3 = log10(ferritin.d3)
  )

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(ICANS0 ~ ferritin.d3 + CAR.T.Product.Type, data=data1)
df1 <- data.frame(Predict(fit,ferritin.d3,fun = plogis))


fit2 <- lrm(ICANS1.2 ~ ferritin.d3 + CAR.T.Product.Type, data=data1)
df2 <- data.frame(Predict(fit2,ferritin.d3,fun = plogis))

fit3 <- lrm(ICANS3.4 ~ ferritin.d3 + CAR.T.Product.Type, data=data1)
df3 <- data.frame(Predict(fit3,ferritin.d3,fun = plogis))

ggplot() + 
  geom_line(data=df1, aes(x=ferritin.d3,y=yhat, color = "G0 ICANS")) + geom_ribbon( data=df1, aes(x=ferritin.d3,ymin=lower, ymax=upper),alpha=0.10)+
  geom_line(data=df2, aes(x=ferritin.d3,y=yhat, color ="G1-2 ICANS" )) + geom_ribbon(data = df2, aes(x=ferritin.d3,ymin=lower, ymax=upper),alpha=0.10)+
    geom_line(data=df3, aes(x=ferritin.d3,y=yhat, color ="G\u22653 ICANS" )) + geom_ribbon(data = df3, aes(x=ferritin.d3,ymin=lower, ymax=upper),alpha=0.10)+
  labs(x = "log(ferritin, day 3) (ng/mL)",
       y = "Probability")+
  theme_bw() +
  scale_y_continuous(breaks=c(0,0.2,0.4,0.6,0.8,1.0), limits=c(0, 1)) + 
  #theme(legend.position = c(0, 1),legend.justification = c(-4.5, 1.1))+
  scale_color_manual(values = c ("steelblue","coral2","purple")) + 
  theme(title = element_text(size=20,face="bold"),legend.title=element_blank())

Probability of CRS based on day 3 ferritin

Show code
data1 <- filter(dataset, Infused == 1) %>%
  mutate(
    ICANS0 = ifelse( ICANS.grade==0,1,0),
    ICANS1.2 = ifelse( ICANS.grade==1 | ICANS.grade == 2,1,0),
    ICANS.any.grade = ifelse( ICANS.grade != 0 ,1,0),
    ICANS3.4 = ifelse( ICANS.grade==3 | ICANS.grade == 4,1,0),
    CRS0 = ifelse( CRS.grade==0,1,0),
    CRS1.2 = ifelse( CRS.grade==1 | CRS.grade == 2,1,0),
    CRS.any.grade = ifelse( CRS.grade != 0 ,1,0),
    CRS3.4 = ifelse( CRS.grade==3 | CRS.grade == 4,1,0),
    
    ferritin.ratio = log(ferritin.d3 / ferritin.d0),
    ferritin.d3 = log10(ferritin.d3)
  )

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(CRS0 ~ ferritin.d3 + CAR.T.Product.Type, data=data1)
df1 <- data.frame(Predict(fit,ferritin.d3,fun = plogis))


fit2 <- lrm(CRS1.2 ~ ferritin.d3 + CAR.T.Product.Type, data=data1)
df2 <- data.frame(Predict(fit2,ferritin.d3,fun = plogis))

fit3 <- lrm(CRS3.4 ~ ferritin.d3 + CAR.T.Product.Type, data=data1)
df3 <- data.frame(Predict(fit3,ferritin.d3,fun = plogis))

ggplot() + 
  geom_line(data=df1, aes(x=ferritin.d3,y=yhat, color = "G0 CRS")) + geom_ribbon( data=df1, aes(x=ferritin.d3,ymin=lower, ymax=upper),alpha=0.10)+
  geom_line(data=df2, aes(x=ferritin.d3,y=yhat, color ="G1-2 CRS" )) + geom_ribbon(data = df2, aes(x=ferritin.d3,ymin=lower, ymax=upper),alpha=0.10)+
    geom_line(data=df3, aes(x=ferritin.d3,y=yhat, color ="G\u22653 CRS" )) + geom_ribbon(data = df3, aes(x=ferritin.d3,ymin=lower, ymax=upper),alpha=0.10)+
  labs(x = "log(ferritin, day 3) (ng/mL)",
       y = "Probability")+
  theme_bw() +
  scale_y_continuous(breaks=c(0,0.2,0.4,0.6,0.8,1.0), limits=c(0, 1)) + 
  #theme(legend.position = c(0, 1),legend.justification = c(-4.5, 1.1))+
  scale_color_manual(values = c ("steelblue","coral2","purple")) + 
  theme(title = element_text(size=20,face="bold"),legend.title=element_blank())

Probability of RESPONSE based on day 3 ferritin

Show code
data1 <- filter(dataset, Infused == 1) %>%
  mutate(
    ICANS0 = ifelse( ICANS.grade==0,1,0),
    ICANS1.2 = ifelse( ICANS.grade==1 | ICANS.grade == 2,1,0),
    ICANS.any.grade = ifelse( ICANS.grade != 0 ,1,0),
    ICANS3.4 = ifelse( ICANS.grade==3 | ICANS.grade == 4,1,0),
    CRS0 = ifelse( CRS.grade==0,1,0),
    CRS1.2 = ifelse( CRS.grade==1 | CRS.grade == 2,1,0),
    CRS.any.grade = ifelse( CRS.grade != 0 ,1,0),
    CRS3.4 = ifelse( CRS.grade==3 | CRS.grade == 4,1,0),
    
    ferritin.ratio = log(ferritin.d3 / ferritin.d0),
    ferritin.d3 = log10(ferritin.d3)
  )

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(Best.CR ~ ferritin.d3 + CAR.T.Product.Type, data=data1)
df1 <- data.frame(Predict(fit,ferritin.d3,fun = plogis))


fit2 <- lrm(Best.PR ~ ferritin.d3 + CAR.T.Product.Type, data=data1)
df2 <- data.frame(Predict(fit2,ferritin.d3,fun = plogis))

fit3 <- lrm(Best.PD ~ ferritin.d3 + CAR.T.Product.Type, data=data1)
df3 <- data.frame(Predict(fit3,ferritin.d3,fun = plogis))

ggplot() + 
  geom_line(data=df1, aes(x=ferritin.d3,y=yhat, color = "CR")) + geom_ribbon( data=df1, aes(x=ferritin.d3,ymin=lower, ymax=upper),alpha=0.10)+
  geom_line(data=df2, aes(x=ferritin.d3,y=yhat, color ="PR" )) + geom_ribbon(data = df2, aes(x=ferritin.d3,ymin=lower, ymax=upper),alpha=0.10)+
    geom_line(data=df3, aes(x=ferritin.d3,y=yhat, color ="PD" )) + geom_ribbon(data = df3, aes(x=ferritin.d3,ymin=lower, ymax=upper),alpha=0.10)+
  labs(x = "log(ferritin, day 3) (ng/mL)",
       y = "Probability")+
  theme_bw() +
  scale_y_continuous(breaks=c(0,0.2,0.4,0.6,0.8,1.0), limits=c(0, 1)) + 
  #theme(legend.position = c(0, 1),legend.justification = c(-8.5, 1.1))+
  scale_color_manual(values = c ("steelblue","coral2","purple")) + 
  theme(title = element_text(size=20,face="bold"),legend.title=element_blank())

Probability of CR or PD based on day 3 ferritin - RESTRICTED CUBIC SPLINES model

Show code
data1 <- filter(dataset, Infused == 1) %>%
  mutate(
    ICANS0.2 = ifelse( as.numeric(ICANS.grade)<=2,1,0),
    ICANS.any.grade = ifelse( ICANS.grade != 0 ,1,0),
    ICANS3.4 = ifelse( ICANS.grade ==3 | ICANS.grade == 4,1,0),
    ferritin.ratio = ferritin.d3 / ferritin.d0
    #ferritin.d3 = log(ferritin.d3)
  )

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(Best.CR ~ rcs(ferritin.d3,3), data=data1)

df1 <- data.frame(Predict(fit,ferritin.d3,fun = plogis))



fit2 <- lrm(Best.PD ~ rcs(ferritin.d3,3), data=data1)
df2 <- data.frame(Predict(fit2,ferritin.d3,fun = plogis))

ggplot() + 
  geom_line(data=df1, aes(x=ferritin.d3,y=yhat, color = "CR")) + geom_ribbon( data=df1, aes(x=ferritin.d3,ymin=lower, ymax=upper),alpha=0.10)+
  geom_line(data=df2, aes(x=ferritin.d3,y=yhat, color ="PD" )) + geom_ribbon(data = df2, aes(x=ferritin.d3,ymin=lower, ymax=upper),alpha=0.10)+
  labs(x = "Ferritin, day 3 (ng/mL)",
       y = "Probability")+
  theme_bw() +
  scale_y_continuous(breaks=c(0,0.2,0.4,0.6,0.8,1.0), limits=c(0, 1)) + 
  #scale_x_continuous(breaks=c(0.25,0.5,0.75,1.0,1.25,1.5,1.75), limits=c(0.25, 1.75)) + 
  #theme(legend.position = c(0, 1),legend.justification = c(-9, 1.1))+
  scale_color_manual(values = c ("steelblue","coral2")) + 
  theme(title = element_text(size=20,face="bold"),legend.title=element_blank())

Hazard of OS and PFS: D3 ferritin

Show code
data1 <- filter(dataset, Infused == 1) %>%
  mutate(
    ferritin.d3 = log10(ferritin.d3)
  )

dd <- datadist(data1)
options(datadist='dd')

S1 <- Surv(data1$Days.to.DLC, data1$Death)
f1 <- cph(S1 ~ ferritin.d3 , x=TRUE, y=TRUE,surv=TRUE,data=data1)
model1 <- Predict(f1, ferritin.d3, fun=function(x) exp(x) )


S2 <- Surv(data1$Days.to.relapse.death.or.DLC, data1$Relapse.or.death)
f2 <- cph(S2 ~ ferritin.d3 , x=TRUE, y=TRUE,surv=TRUE,data=data1)
model2 <- Predict(f2, ferritin.d3, fun=function(x) exp(x) )

ggplot() + 
  geom_line(data=model1, aes(x=ferritin.d3, y=yhat, color = "OS")) +  geom_ribbon(data = model1, aes(x=ferritin.d3, ymin=lower, ymax=upper), alpha=0.1) + 
  geom_line(data=model2, aes(x=ferritin.d3, y=yhat, color = "PFS")) +  geom_ribbon(data = model2, aes(x=ferritin.d3, ymin=lower, ymax=upper), alpha=0.1) +
  theme_bw() + 
  labs(
    #title = "Survival by product and ferritin at day 3",
    x = "log(ferritin, day 3)",
    y = "Hazard") +
  #theme(legend.position = c(0, 1),legend.justification = c(-0.8, 1.2))+
  scale_color_manual(values = c ("coral2","steelblue")) + 
  theme(title = element_text(size=20,face="bold"),legend.title=element_blank())

Hazard of PFS: D3 ferritin

Show code
data1 <- filter(dataset, Infused == 1) %>%
  mutate(
    ferritin.d3 = log10(ferritin.d3)
  )

dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.relapse.death.or.DLC, data1$Relapse.or.death)
f <- cph(S ~ ferritin.d3 , x=TRUE, y=TRUE,surv=TRUE,data=data1)

model <- Predict(f, ferritin.d3, fun=function(x) exp(x) )

ggplot(as.data.frame(model),aes(x=ferritin.d3, y=yhat)) + 
  geom_line(
    aes()
  ) + 
  geom_ribbon(data = model, aes(ymin=lower, ymax=upper), alpha=0.2, linetype=0) + 
  theme_bw() + 
  labs(
    #title = "Survival by product and ferritin at day 3",
    x = "log(ferritin), day 3",
    y = "PFS (hazard)") +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Hazard of PFS: D3 ferritin - stratified by CAR-T-product

Show code
data1 <- filter(dataset, Infused == 1) %>%
  mutate(
    ferritin.d3 = log10(ferritin.d3)
  )

dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.relapse.death.or.DLC, data1$Relapse.or.death)
f <- cph(S ~ ferritin.d3 + CAR.T.Product.Type , x=TRUE, y=TRUE,surv=TRUE,data=data1)

model <- Predict(f, CAR.T.Product.Type, ferritin.d3, fun=function(x) exp(x) )

ggplot(as.data.frame(model),aes(x=ferritin.d3, y=yhat, z = CAR.T.Product.Type)) + 
  geom_line(
    aes(col = CAR.T.Product.Type)
  ) + 
  geom_ribbon(data = model, aes(ymin=lower, ymax=upper), alpha=0.2, linetype=0) + 
  theme_bw() + 
  labs(
    #title = "Survival by product and ferritin at day 3",
    x = "log(ferritin), day 3",
    y = "PFS (hazard)") +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

ICANS/CRS

Probability of Grade 0-2 and Grade 3-4 ICANS: LDH pre-LD (RCS)

Show code
data1 <- filter(dataset, Infused == 1) %>%
  mutate(
    ICANS0.2 = ifelse( ICANS.grade == 2 | ICANS.grade == 1 | ICANS.grade == 0,1,0),
    ICANS3.4 = ifelse( ICANS.grade == 3 | ICANS.grade == 4,1,0)
    #ferritin.d3 = log(ferritin.d3)
  )

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(ICANS0.2 ~ rcs(LDH.preLD,3), data=data1)

df1 <- data.frame(Predict(fit,LDH.preLD,fun = plogis))



fit2 <- lrm(ICANS3.4 ~ rcs(LDH.preLD,3), data=data1)
df2 <- data.frame(Predict(fit2,LDH.preLD,fun = plogis))

ggplot() + 
  geom_line(data=df1, aes(x=LDH.preLD,y=yhat, color = "0-2")) + geom_ribbon( data=df1, aes(x=LDH.preLD,ymin=lower, ymax=upper),alpha=0.10)+
  geom_line(data=df2, aes(x=LDH.preLD,y=yhat, color ="3-4" )) + geom_ribbon(data = df2, aes(x=LDH.preLD,ymin=lower, ymax=upper),alpha=0.10)+
  labs(x = "LDH pre-LD (U/L)",
       y = "Probability")+
  theme_bw() +
  scale_y_continuous(breaks=c(0,0.2,0.4,0.6,0.8,1.0), limits=c(0, 1)) + 
  #scale_x_continuous(breaks=c(0.25,0.5,0.75,1.0,1.25,1.5,1.75), limits=c(0.25, 1.75)) + 
  #theme(legend.position = c(0, 1),legend.justification = c(-9, 1.1))+
  scale_color_manual(values = c ("steelblue","coral2")) + 
  theme(title = element_text(size=20,face="bold"),legend.title=element_blank())

Probability of any grade CRS based on Age

Show code
data1 <- filter(dataset, Infused == 1) %>%
  select(CRS.grade, ICANS.grade, Age, CAR.T.Product.Type) %>%
  mutate(
    CRS.any = ifelse( CRS.grade != 0,1,0),
    ICANS.any = ifelse( ICANS.grade !=0,1,0)
  )

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(CRS.any ~ CAR.T.Product.Type *Age, data=data1)

data.frame(Predict(fit,Age,CAR.T.Product.Type,fun = plogis)) %>%
  ggplot() +
  geom_line(aes(x=Age,y=yhat,col=CAR.T.Product.Type)) +
  geom_ribbon(aes(x=Age,ymin=lower, ymax=upper,fill=CAR.T.Product.Type),alpha=0.10)+
  labs(x = "Age (years)",
       y = "Probability of any grade CRS")+
  theme_bw() +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Probability of any grade ICANS based on Age

Show code
data1 <- filter(dataset, Infused == 1) %>%
  select(CRS.grade, ICANS.grade, Age, CAR.T.Product.Type) %>%
  mutate(
    CRS.any = ifelse( CRS.grade != 0,1,0),
    ICANS.any = ifelse( ICANS.grade !=0,1,0)
  )
dd <- datadist(data1)
options(datadist='dd')

dd <- datadist(data1)
options(datadist='dd')

fit <- lrm(ICANS.any ~ CAR.T.Product.Type * Age, data=data1)

data.frame(Predict(fit,Age,CAR.T.Product.Type,fun = plogis)) %>%
  ggplot() +
  geom_line(aes(x=Age,y=yhat,col=CAR.T.Product.Type)) +
  geom_ribbon(aes(x=Age,ymin=lower, ymax=upper,fill=CAR.T.Product.Type),alpha=0.10)+
  labs(x = "Age (years)",
       y = "Probability of any grade ICANS")+
  #scale_x_continuous(labels = alc_breaks,breaks = c(-.5,-.25,0,.25))+
  #ggtitle("Figure.")+
  theme_bw() +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Probability of Any grade and G3+ CRS: Age

Show code
data1 <- filter(dataset, Infused == 1) %>%
  select(CRS.grade, ICANS.grade, Age, CAR.T.Product.Type) %>%
  mutate(
    CRS3.4 = ifelse( CRS.grade == 3 | CRS.grade == 4,1,0),
    ICANS3.4 = ifelse( ICANS.grade == 3 | ICANS.grade == 4,1,0),
    CRS.any = ifelse( CRS.grade !=0 ,1,0),
    ICANS.any = ifelse( ICANS.grade !=0,1,0)
  )

dd <- datadist(data1)
options(datadist='dd')


fit1 <- lrm(CRS3.4 ~ CAR.T.Product.Type + Age, data=data1)

df1 <- data.frame(Predict(fit1,Age,fun = plogis))



fit2 <- lrm(CRS.any ~ CAR.T.Product.Type + Age, data=data1)
df2 <- data.frame(Predict(fit2,Age,fun = plogis))

ggplot() + 
  geom_line(data=df1, aes(x=Age,y=yhat, color = "\u22653")) + geom_ribbon( data=df1, aes(x=Age,ymin=lower, ymax=upper),alpha=0.10)+
  geom_line(data=df2, aes(x=Age,y=yhat, color ="Any" )) + geom_ribbon(data = df2, aes(x=Age,ymin=lower, ymax=upper),alpha=0.10)+
  labs(x = "Age (years)",
       y = "Probability of CRS")+
  theme_bw() +
  scale_y_continuous(breaks=c(0,0.2,0.4,0.6,0.8,1.0), limits=c(0, 1)) + 
  #scale_x_continuous(breaks=c(0.25,0.5,0.75,1.0,1.25,1.5,1.75), limits=c(0.25, 1.75)) + 
  #theme(legend.position = c(0, 1),legend.justification = c(-8.3, 3))+
  scale_color_manual(values = c ("coral2","steelblue")) + 
  theme(title = element_text(size=20,face="bold"),legend.title=element_blank())

Probability of any grade and 3+ ICANS: Age

Show code
data1 <- filter(dataset, Infused == 1) %>%
  select(CRS.grade, ICANS.grade, Age, CAR.T.Product.Type) %>%
  mutate(
    CRS3.4 = ifelse( CRS.grade == 3 | CRS.grade == 4,1,0),
    ICANS3.4 = ifelse( ICANS.grade == 3 | ICANS.grade == 4,1,0),
    CRS.any = ifelse( CRS.grade !=0 ,1,0),
    ICANS.any = ifelse( ICANS.grade !=0,1,0)
  )

dd <- datadist(data1)
options(datadist='dd')

fit1 <- lrm(ICANS3.4 ~ CAR.T.Product.Type + Age, data=data1)
df1 <- data.frame(Predict(fit1,Age,fun = plogis))

fit2 <- lrm(ICANS.any ~ CAR.T.Product.Type + Age, data=data1)
df2 <- data.frame(Predict(fit2,Age,fun = plogis))

ggplot() + 
  geom_line(data=df1, aes(x=Age,y=yhat, color = "\u22653")) + geom_ribbon( data=df1, aes(x=Age,ymin=lower, ymax=upper),alpha=0.10)+
  geom_line(data=df2, aes(x=Age,y=yhat, color ="Any" )) + geom_ribbon(data = df2, aes(x=Age,ymin=lower, ymax=upper),alpha=0.10)+
  labs(x = "Age (years)",
       y = "Probability of ICANS")+
  theme_bw() +
  scale_y_continuous(breaks=c(0,0.2,0.4,0.6,0.8,1.0), limits=c(0, 1)) + 
  #scale_x_continuous(breaks=c(0.25,0.5,0.75,1.0,1.25,1.5,1.75), limits=c(0.25, 1.75)) + 
  #theme(legend.position = c(0, 1),legend.justification = c(-8.3, 1.1))+
  scale_color_manual(values = c ("coral2","steelblue")) + 
  theme(title = element_text(size=20,face="bold"),legend.title=element_blank())

PFS & OS

Hazard of PFS: LDH - stratified by bulky status

Show code
data1 <- filter(dataset, Infused == 1) %>%
  mutate(
    Bulky = recode(Bulky, "1"="Bulky","0"="Not bulky")
  )

dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.relapse.death.or.DLC, data1$Relapse.or.death)
f <- cph(S ~ LDH.preLD * Bulky , x=TRUE, y=TRUE,surv=TRUE,data=data1)

med <- Quantile(f)
model <- Predict(f, Bulky, LDH.preLD, fun=function(x) exp(x) )

ggplot(as.data.frame(model),aes(x=LDH.preLD , y=yhat, z = Bulky)) + 
  geom_line(
    aes(col = Bulky)
  ) + 
  geom_ribbon(data = model, aes(ymin=lower, ymax=upper), alpha=0.2, linetype=0) + 
  theme_bw() + 
  labs(
    #title = "Survival by CAR-T product and ALC pre-LD",
     x = "LDH pre-LD (U/L)",
     y = "PFS (hazard)")+
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Hazard of OS: LDH - stratified by bulky status

Show code
data1 <- filter(dataset, Infused == 1) %>%
  mutate(
    Bulky = recode(Bulky, "1"="Bulky","0"="Not bulky")
  )

dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.DLC, data1$Death)
f <- cph(S ~ LDH.preLD * Bulky , x=TRUE, y=TRUE,surv=TRUE,data=data1)

med <- Quantile(f)
model <- Predict(f, Bulky, LDH.preLD, fun=function(x) exp(x) )

ggplot(as.data.frame(model),aes(x=LDH.preLD , y=yhat, z = Bulky)) + 
  geom_line(
    aes(col = Bulky)
  ) + 
  geom_ribbon(data = model, aes(ymin=lower, ymax=upper), alpha=0.2, linetype=0) + 
  theme_bw() + 
  labs(
    #title = "Survival by CAR-T product and ALC pre-LD",
     x = "LDH pre-LD (U/L)",
     y = "OS (hazard)")+
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Hazard of OS: LDH, stratified

Show code
data1 <- filter(dataset, Infused == 1)

dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.DLC, data1$Death)
f <- cph(S ~ LDH.preLD , x=TRUE, y=TRUE,surv=TRUE,data=data1)

med <- Quantile(f)
model <- Predict(f, LDH.preLD, fun=function(x) exp(x) )

ggplot(as.data.frame(model),aes(x=LDH.preLD , y=yhat)) + 
  geom_line() + 
  geom_ribbon(data = model, aes(ymin=lower, ymax=upper), alpha=0.2, linetype=0) + 
  theme_bw() + 
  labs(
    #title = "Survival by LDH pre-LD",
    x = "LDH pre-LD (U/L)",
    y = "OS (hazard)")+
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Hazard of PFS: LDH, stratified by product

Show code
data1 <- filter(dataset, Infused == 1) 

dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.relapse.death.or.DLC, data1$Relapse.or.death)
f <- cph(S ~ LDH.preLD * CAR.T.Product.Type , x=TRUE, y=TRUE,surv=TRUE,data=data1)



model <- Predict(f, CAR.T.Product.Type, LDH.preLD, fun=function(x) exp(x) )

ggplot(as.data.frame(model),aes(x=LDH.preLD, y=yhat, z = CAR.T.Product.Type)) + 
  geom_line(
    aes(col = CAR.T.Product.Type)
  ) + 
  geom_ribbon(data = model, aes(ymin=lower, ymax=upper), alpha=0.2, linetype=0) + 
  theme_bw() + 
  labs(
    #title = "Survival by product and LDH pre-LD",
    x = "LDH pre-LD (U/L)",
    y = "PFS (hazard)") +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Hazard of PFS: LDH, stratified by bulky status

Show code
data1 <- filter(dataset, Infused == 1) %>%
  mutate(
    Bulky = recode(Bulky,"1"="Bulky","0"="Not bulky")
  )

dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.relapse.death.or.DLC, data1$Relapse.or.death)
f <- cph(S ~ LDH.preLD * Bulky , x=TRUE, y=TRUE,surv=TRUE,data=data1)

model <- Predict(f, Bulky, LDH.preLD, fun=function(x) exp(x) )

ggplot(as.data.frame(model),aes(x=LDH.preLD, y=yhat, z = Bulky)) + 
  geom_line(
    aes(col = Bulky)
  ) + 
  geom_ribbon(data = model, aes(ymin=lower, ymax=upper), alpha=0.2, linetype=0) + 
  theme_bw() + 
  labs(
    #title = "Survival by product and LDH pre-LD",
    x = "LDH pre-LD (U/L)",
    y = "PFS (hazard)") +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Hazard of OS: LDH, stratified by bulky status

Show code
data1 <- filter(dataset, Infused == 1)%>%
  mutate(
    Bulky = recode(Bulky,"1"="Bulky","0"="Not bulky")
  )

dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.DLC, data1$Death)
f <- cph(S ~ LDH.preLD * Bulky , x=TRUE, y=TRUE,surv=TRUE,data=data1)

model <- Predict(f, Bulky, LDH.preLD, fun=function(x) exp(x) )

ggplot(as.data.frame(model),aes(x=LDH.preLD, y=yhat, z = Bulky)) + 
  geom_line(
    aes(col = Bulky)
  ) + 
  geom_ribbon(data = model, aes(ymin=lower, ymax=upper), alpha=0.2, linetype=0) + 
  theme_bw() + 
  labs(
    #title = "Survival by product and LDH pre-LD",
    x = "LDH pre-LD (U/L)",
    y = "OS (hazard)") +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Hazard of PFS: LDH

Show code
data1 <- filter(dataset, Infused == 1)

dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.relapse.death.or.DLC, data1$Relapse.or.death)
f <- cph(S ~ LDH.preLD , x=TRUE, y=TRUE,surv=TRUE,data=data1)

model <- Predict(f, LDH.preLD, fun=function(x) exp(x) )

ggplot(as.data.frame(model),aes(x=LDH.preLD, y=yhat)) + 
  geom_line(
    aes()
  ) + 
  geom_ribbon(data = model, aes(ymin=lower, ymax=upper), alpha=0.2, linetype=0) + 
  theme_bw() + 
  labs(
    #title = "Survival by product and LDH pre-LD",
    x = "LDH pre-LD (U/L)",
    y = "PFS (hazard)") +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Hazard of OS: Largest lesion

Show code
data1 <- dataset

dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.DLC, data1$Death)
f <- cph(S ~ Largest.lesion, x=TRUE, y=TRUE,surv=TRUE,data=data1)

med <- Quantile(f)
model <- Predict(f, Largest.lesion, fun=function(x) exp(x) )

ggplot(as.data.frame(model),aes(x=Largest.lesion , y=yhat)) + 
  geom_line() + 
  geom_ribbon(data = model, aes(ymin=lower, ymax=upper), alpha=0.2, linetype=0) + 
  theme_bw() + 
  labs(
    #title = "Survival by LDH pre-LD",
    x = "Largest lesion (cm)",
    y = "OS (hazard)")+
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

Hazard of OS: Cr

Show code
data1 <- filter(dataset, Infused == 1) 

dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.DLC, data1$Death)
f <- cph(S ~ rcs(cre.preLD,3) , x=TRUE, y=TRUE,surv=TRUE,data=data1)



model <- Predict(f, cre.preLD, fun=function(x) exp(x) )

ggplot(as.data.frame(model),aes(x=cre.preLD, y=yhat)) + 
  geom_line(
    aes()
  ) + 
  geom_ribbon(data = model, aes(ymin=lower, ymax=upper), alpha=0.2, linetype=0) + 
  theme_bw() + 
  labs(
    #title = "Survival by product and pre-LD Cr",
    x = "Pre-LD Cr (U/L)",
    y = "OS (hazard)") +
  theme(title = element_text(size=16,face="bold"),legend.title=element_blank())

CURVE SMOOTHING

ANC Loess modeling – stratified by product

Show code
data1 <- CBCdata %>%
  mutate(
    CAR.T.Product.Type = recode(CAR.T.Product.Type, "Breyanzi" = "Liso-cel", "Yescarta" = "Axi-cel")
  )

ggplot() + 
  geom_smooth(data = filter(data1, CAR.T.Product.Type == "Liso-cel"), aes(x = day, y = ancx, color = "Liso-cel"), method = "loess", formula = y~x, fill = "#69b3a2", se = TRUE, na.rm = TRUE) + 
  geom_smooth(data = filter(data1, CAR.T.Product.Type == "Axi-cel"), aes(x = day, y = ancx, color = "Axi-cel"), method = "loess", formula = y~x, fill = "#69b3a2", se = TRUE, na.rm = TRUE) + 
  labs(
    x = "Time relative to infusion (days)",
    y = "Absolute neutrophil count (cells/µL)",
    color = "Legend"
  ) + 
  scale_y_continuous(breaks = c(0, 1000, 2000, 3000, 4000, 5000, 6000)) +
  xlim(-5, 50) +
  theme_classic() + 
  theme(legend.position = c(0.8, 0.9)) +
  scale_color_manual(values = c("steelblue", "coral2")) +
  theme(text = element_text(size = 16))

Plt Loess modeling – stratified by product

Show code
data1 <- CBCdata %>%
  mutate(
    CAR.T.Product.Type = recode(CAR.T.Product.Type, "Breyanzi" = "Liso-cel", "Yescarta" = "Axi-cel")
  )

ggplot() + 
  geom_smooth(data = filter(data1, CAR.T.Product.Type == "Liso-cel"), aes(x=day, y=TotPlateletCnt/1000, color = "Liso-cel"), method="loess" , formula = y~x, fill="#69b3a2", se=TRUE, na.rm = TRUE) + 
  geom_smooth(data = filter(data1, CAR.T.Product.Type == "Axi-cel"), aes(x=day, y=TotPlateletCnt/1000, color = "Axi-cel"),method="loess" , formula = y~x , fill="#69b3a2", se=TRUE, na.rm = TRUE) + 
  labs(x = "Time relative to infusion (days)",
       y = "Platelet count (10\u00B3/\u00B5L)",
       color = "Legend") + 
  theme_classic() + 
  xlim(-5,50) +
  scale_color_manual(values = c ("steelblue","coral2")) + 
  theme(legend.position=c(.8,.9)) +
  theme(text = element_text(size = 16))  

Ferritin Loess modeling – stratified by CRS

Show code
ferritin.data = filter(labs, day >=-5 & day <=30) %>%
  select(day, time, ferritin_ng_ml, uwid) %>%
  mutate(
    time.percent = sapply( strsplit(time,":"),
                           function(x) {
                             x <- as.numeric(x)
                             x[1]/24
                           }
    ),
    day = ifelse(day>=0, day + time.percent, day - time.percent),
    ferritin = log10(ferritin_ng_ml)
  )

ferritin.data <-
  left_join(
    x = ferritin.data,
    y = dataset %>%
      select(CAR.T.Product.Type, CRS.grade, uwid, Study.No),
    by = "uwid"
  )

ggplot() + 
    geom_smooth(data = filter(ferritin.data, CRS.grade == "3" | CRS.grade == "4"), aes(x=day, y=ferritin_ng_ml, color = "G\u22653 CRS"),method="loess" , formula = y~x , fill="#69b3a2", se=TRUE, na.rm = TRUE) + 
  geom_smooth(data = filter(ferritin.data, CRS.grade == "1" | CRS.grade == "2"), aes(x=day, y=ferritin_ng_ml, color = "G1-2 CRS"),method="loess" , formula = y~x , fill="#69b3a2", se=TRUE, na.rm = TRUE) + 
    geom_smooth(data = filter(ferritin.data, CRS.grade == "0"), aes(x=day, y=ferritin_ng_ml, color = "G0 CRS"),method="loess" , formula = y~x , fill="#69b3a2", se=TRUE, na.rm = TRUE) + 
  labs(x = "Time relative to infusion (days)",
       y = "Ferritin (ng/mL)",
       color = "Legend") +
  theme_classic() + 
  theme(legend.position=c(.8,.8)) +
  theme(text = element_text(size = 16))  +
  scale_color_manual(values = c ("coral2","purple","steelblue")) +
  coord_cartesian(ylim = c(0, 9000), xlim = c(0, 30))

Ferritin Loess modeling – stratified by ICANS

Show code
ferritin.data = filter(labs, day >=-5 & day <=30) %>%
  select(day, time, ferritin_ng_ml, uwid) %>%
  mutate(
    time.percent = sapply( strsplit(time,":"),
                           function(x) {
                             x <- as.numeric(x)
                             x[1]/24
                           }
    ),
    day = ifelse(day>=0, day + time.percent, day - time.percent),
    ferritin = log10(ferritin_ng_ml)
  )

ferritin.data <-
  left_join(
    x = ferritin.data,
    y = dataset %>%
      select(CAR.T.Product.Type, CRS.grade, ICANS.grade, uwid, Study.No),
    by = "uwid"
  )

ggplot() + 
    geom_smooth(data = filter(ferritin.data, ICANS.grade == "3" | CRS.grade == "4"), aes(x=day, y=ferritin_ng_ml, color = "G\u22653 ICANS"),method="loess" , formula = y~x , fill="#69b3a2", se=TRUE, na.rm = TRUE) + 
  geom_smooth(data = filter(ferritin.data, ICANS.grade == "1" | CRS.grade == "2"), aes(x=day, y=ferritin_ng_ml, color = "G1-2 ICANS"),method="loess" , formula = y~x , fill="#69b3a2", se=TRUE, na.rm = TRUE) + 
    geom_smooth(data = filter(ferritin.data, ICANS.grade == "0"), aes(x=day, y=ferritin_ng_ml, color = "G0 ICANS"),method="loess" , formula = y~x , fill="#69b3a2", se=TRUE, na.rm = TRUE) + 
  labs(x = "Time relative to infusion (days)",
       y = "Ferritin (ng/mL)",
       color = "Legend") + 
  theme_classic() + 
  theme(legend.position=c(.2,.8)) +
  theme(text = element_text(size = 16))  +
  scale_color_manual(values = c ("coral2","purple","steelblue")) +
  coord_cartesian(ylim = c(0, 9000), xlim = c(0, 30))

Ferritin Loess modeling – stratified by response

Show code
ferritin.data = filter(labs, day >=-5 & day <=30) %>%
  select(day, time, ferritin_ng_ml, uwid) %>%
  mutate(
    time.percent = sapply( strsplit(time,":"),
                           function(x) {
                             x <- as.numeric(x)
                             x[1]/24
                           }
    ),
    day = ifelse(day>=0, day + time.percent, day - time.percent),
    ferritin = log10(ferritin_ng_ml)
  )

ferritin.data <-
  left_join(
    x = ferritin.data,
    y = dataset %>%
      select(CAR.T.Product.Type, CRS.grade, ICANS.grade, uwid, Study.No, Best.CR, Best.PR, Best.PD),
    by = "uwid"
  )

ggplot() + 
    geom_smooth(data = filter(ferritin.data, Best.CR == 1), aes(x=day, y=ferritin_ng_ml, color = "CR"),method="loess" , formula = y~x , fill="#69b3a2", se=TRUE, na.rm = TRUE) + 
  geom_smooth(data = filter(ferritin.data, Best.PR == 1), aes(x=day, y=ferritin_ng_ml, color = "PR"),method="loess" , formula = y~x , fill="#69b3a2", se=TRUE, na.rm = TRUE) + 
    geom_smooth(data = filter(ferritin.data, Best.PD == 1), aes(x=day, y=ferritin_ng_ml, color = "PD"),method="loess" , formula = y~x , fill="#69b3a2", se=TRUE, na.rm = TRUE) + 
  labs(x = "Time relative to infusion (days)",
       y = "Ferritin (ng/mL)",
       color = "Legend") + 
  theme_classic() + 
  theme(legend.position=c(.2,.8)) +
  theme(text = element_text(size = 16))  +
  scale_color_manual(values = c ("coral2","purple","steelblue")) +
  coord_cartesian(ylim = c(0, 9000), xlim = c(0, 30))

Ferritin Loess modeling – stratified by product

Show code
ferritin.data = filter(labs, day >=-5 & day <=30) %>%
  select(day, time, ferritin_ng_ml, uwid) %>%
  mutate(
    time.percent = sapply( strsplit(time,":"),
                           function(x) {
                             x <- as.numeric(x)
                             x[1]/24
                           }
    ),
    day = ifelse(day>=0, day + time.percent, day - time.percent),
    ferritin = log10(ferritin_ng_ml)
  )

ferritin.data <-
  left_join(
    x = ferritin.data,
    y = dataset %>%
      select(CAR.T.Product.Type, CRS.grade, ICANS.grade, uwid, Study.No, Best.CR, Best.PR, Best.PD),
    by = "uwid"
  )

ggplot() + 
    geom_smooth(data = filter(ferritin.data, CAR.T.Product.Type == "Breyanzi"), aes(x=day, y=ferritin_ng_ml, color = "Liso-cel"),method="loess" , formula = y~x , fill="#69b3a2", se=TRUE, na.rm = TRUE) + 
  geom_smooth(data = filter(ferritin.data, CAR.T.Product.Type == "Yescarta"), aes(x=day, y=ferritin_ng_ml, color = "Axi-cel"),method="loess" , formula = y~x , fill="#69b3a2", se=TRUE, na.rm = TRUE) + 
  labs(x = "Time relative to infusion (days)",
       y = "Ferritin (ng/mL)",
       color = "Legend") + 
  theme_classic() + 
  theme(legend.position=c(.2,.8)) +
  theme(text = element_text(size = 16))  +
  scale_color_manual(values = c ("coral2","purple","steelblue")) +
  coord_cartesian(ylim = c(0, 5000), xlim = c(0, 30))

CONTOUR PLOTS

Contour plot for largest lesion and LDH pre-LD

Show code
data1 <- filter(dataset, CAR.T.Product.Type == "Breyanzi")
dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.DLC/30, data1$Death)
f <- cph(S ~ Largest.lesion * LDH.preLD , x=TRUE, y=TRUE,surv=TRUE,data=data1)


med <- Quantile(f)
data.frame(Predict(f,Largest.lesion,LDH.preLD,fun=function(x) med(lp=x))) %>%
  ggplot() +
  geom_contour_filled(aes(Largest.lesion,LDH.preLD, z = yhat)) +
  theme_classic() +
  labs(title = "Liso-cel",
       x = "Largest lesion (cm)",
       y = "LDH pre-LD (U/L)",
       fill="Median survival (months)")  +
  coord_cartesian(xlim = c(0, 10), ylim = c(100, 700))
Show code
data1 <- filter(dataset, CAR.T.Product.Type == "Yescarta") %>%
  select(Largest.lesion, LDH.preLD, Days.to.DLC, Death
  )
dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.DLC/30, data1$Death)
f <- cph(S ~ Largest.lesion * LDH.preLD , x=TRUE, y=TRUE,surv=TRUE,data=data1)

med <- Quantile(f)
data.frame(Predict(f,Largest.lesion,LDH.preLD,fun=function(x) med(lp=x))) %>%
  ggplot() +
  geom_contour_filled(aes(Largest.lesion,LDH.preLD, z = yhat)) +
  theme_classic() +
  labs(title = "Axi-cel",
       x = "Largest lesion (cm)",
       y = "LDH pre-LD (U/L)",
       fill="Median survival (months)") +
  coord_cartesian(xlim = c(0, 10), ylim = c(100, 700))

Contour plot for Age and ALC pre-LD

Show code
data1 <- filter(dataset, Infused == 1)
dd <- datadist(data1)
options(datadist='dd')

S <- Surv(data1$Days.to.DLC, data1$Death)
f <- cph(S ~ Age * ALC.preLD , x=TRUE, y=TRUE,surv=TRUE,data=data1)

med <- Quantile(f)
data.frame(Predict(f,Age,ALC.preLD,fun=function(x) med(lp=x)/365.25)) %>%
  ggplot() +
  geom_contour_filled(aes(Age,ALC.preLD, z = yhat)) +
  theme_classic() +
  labs(title = "Survival: ALC pre-LD and Age",
       x = "Age (years)",
       y = "ALC pre-LD (10\U00B3/\U00B5L)",
       fill="Median survival (years)") 

Swimmer’s plot

Swimmer plot

Show code
swimmer_data = as.data.frame(read_excel(path = "Swimmer.xlsx")) %>%
  mutate(
    Response_start = Response_start/30,
    Response_end = Response_end/30,
    Time = Time/30,
    Product = recode(Product, "Breyanzi" = "Liso-cel","Yescarta"="Axi-cel"),
    Response = factor(Response, levels = c("CR","PR","SD", "PD"))
  )

pastel1_palette <- brewer.pal(4, "Pastel1")[c(3,2,4,1)]


swimmer <- swimmer_plot(df=filter(swimmer_data, !is.na(Response) ), 
            id="Number",
            end= "Response_end", 
            name_fill="Response",
            stratify = "Product",
            ) +
  scale_fill_manual(values = pastel1_palette) +
  swimmer_arrows(df_arrows = filter(swimmer_data,!is.na(Continued_response) ),
                 id="Number",
                 arrow_start="Response_end", 
                 name_col = 'Response', 
                 type = "closed", cex=.5, 
                 arrow_positions = c(1,6)
                 )+ 
  scale_color_manual(name="Response",values=pastel1_palette,drop=FALSE) +
  swimmer_points(df_points= filter(swimmer_data,!is.na(Event) ) ,id='Number',name_shape = "Event", time='Time',size=1,fill='white',col="black") +
  scale_y_continuous(name = "Time since infusion (Months)",breaks = seq(0,10000,by=12)) +
  guides(fill = guide_legend(title = "Response"), colour = FALSE)  # Hide the legend for arrows
swimmer